本文介绍了在ASP.NET 5 Imlementing定制IRouter(vNext)MVC 6的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图转换this样品RouteBase实施通过以下the例如,在路由项目,但我正在逐渐绊倒如何从该方法返回异步工作。我真的不关心,如果它实际上是异步的(欢呼的人谁可以提供答案),现在我只想把它发挥作用。

我即将离任的路由功能(即 ActionLink的当我把在路由值正常工作)。问题是与 RouteAsync 方法。

 公共任务RouteAsync(RouteContext上下文)
{
    VAR requestPath = context.HttpContext.Request.Path.Value;    如果(string.IsNullOrEmpty(requestPath)及!&放大器; requestPath [0] =='/')
    {
        //修剪前导斜杠
        requestPath = requestPath.Substring(1);
    }    //获取相匹配的页面。
    VAR页= GetPageList()
        。凡(X => x.VirtualPath.Equals(requestPath))
        .FirstOrDefault();    //如果我们回到一个空值设置,这意味着URI不匹配
    如果(页面!= NULL)
    {
        VAR的RouteData =新的RouteData();        //这不起作用
        // VAR的RouteData =新的RouteData(context.RouteData);        //这不起作用
        //routeData.Routers.Add(this);        //这不起作用
        //routeData.Routers.Add(new MvcRouteHandler());        // TODO:您可能希望使用页面对象(从数据库)来
        //取得两个控制器和动作,甚至可能的区域。
        //或者,您可以创建为每个表和硬code路线
        // 此信息。
        routeData.Values​​ [控制器] =CustomPage;
        routeData.Values​​ [行动] =详细信息;        //这将是数据库行的主键。
        //这可能是一个整数或GUID。
        routeData.Values​​ [ID] = page.Id;        context.RouteData =的RouteData;        //当有匹配,code执行在这里
        context.IsHandled = TRUE;        //这个测​​试工作
        //等待context.HttpContext.Response.WriteAsync(你好);        //这不起作用
        //返回Task.FromResult(的RouteData);        //这不起作用
        //返回Task.FromResult(背景);
    }    //这满足了return语句,但
    //我不知道它是返回正确的事情。
    返回Task.FromResult(0);
}

整个方法运行一路过关斩将到最后的时候有一个匹配。但是,当它执行完毕,它不叫详细信息 CustomPage 控制器的方法,因为它应该。我只是得到一个空白页面在浏览器。

我添加了 WriteAsync 行是在的并将其写入你好来的空白页,但我不明白为什么MVC是不是要求我的控制器(以previous版本,这个工作很顺利)。不幸的是,该职位涵盖除了如何实现路由的每一个部分的 IRouter INamedRouter

我怎样才能让 RouteAsync 方法函数?

整个CustomRoute实施

 使用Microsoft.AspNet.Routing;
使用Microsoft.Framework.Caching.Memory;
使用系统;
使用System.Collections.Generic;
使用System.Linq的;
使用System.Threading.Tasks;公共类PageInfo
{
    // VirtualPath不应该有一个斜线
    //例如:活动/会议/ mycon
    公共字符串VirtualPath {搞定;组; }
    公众诠释标识{搞定;组; }
}公共接口ICustomRoute:IRouter
{}
公共类CustomRoute:ICustomRoute
{
    私人只读IMemoryCache缓存;
    私有对象的SyncLock =新的对象();    公共CustomRoute(IMemoryCache缓存)
    {
        this.cache =高速缓存;
    }    公共任务RouteAsync(RouteContext上下文)
    {
        VAR requestPath = context.HttpContext.Request.Path.Value;        如果(string.IsNullOrEmpty(requestPath)及!&放大器; requestPath [0] =='/')
        {
            //修剪前导斜杠
            requestPath = requestPath.Substring(1);
        }        //获取相匹配的页面。
        VAR页= GetPageList()
            。凡(X => x.VirtualPath.Equals(requestPath))
            .FirstOrDefault();        //如果我们回到一个空值设置,这意味着URI不匹配
        如果(页面!= NULL)
        {
            VAR的RouteData =新的RouteData();            // TODO:您可能希望使用页面对象(从数据库)来
            //取得两个控制器和动作,甚至可能的区域。
            //或者,您可以创建为每个表和硬code路线
            // 此信息。
            routeData.Values​​ [控制器] =CustomPage;
            routeData.Values​​ [行动] =详细信息;            //这将是数据库行的主键。
            //这可能是一个整数或GUID。
            routeData.Values​​ [ID] = page.Id;            context.RouteData =的RouteData;
            context.IsHandled = TRUE;
        }        返回Task.FromResult(0);
    }    公共VirtualPathData GetVirtualPath(VirtualPathContext上下文)
    {
        VirtualPathData结果= NULL;
        PageInfo页= NULL;        //获取所有缓存中的网页。
        变种页= GetPageList();        如果(TryFindMatch(页,context.Values​​,走出页))
        {
            结果=新VirtualPathData(这一点,page.VirtualPath);
            context.IsBound = TRUE;
        }        返回结果;
    }    私人布尔TryFindMatch(IEnumerable的< PageInfo>页,IDictionary的<字符串对象>值,出PageInfo页)
    {
        页= NULL;
        INT ID;
        反对idObj;
        对象控制器;
        对象操作;        如果(!values​​.TryGetValue(ID,出idObj))
        {
            返回false;
        }        ID = Convert.ToInt32(idObj);
        values​​.TryGetValue(控制器,走出控制器);
        values​​.TryGetValue(行动,出于行动);        //这里的逻辑应的逻辑在逆
        // GetRouteData()。所以,我们匹配相同的控制器,操作和ID。
        //如果我们有更多的路由值在那里,我们将采取所有这些
        在该步骤期间//考虑。
        如果(action.Equals(详细信息)及和放大器; controller.Equals(CustomPage))
        {
            页=页
                。凡(X => x.Id.Equals(ID))
                .FirstOrDefault();
            如果(页面!= NULL)
            {
                返回true;
            }
        }
        返回false;
    }    私人的IEnumerable< PageInfo> GetPageList()
    {
        字符串键=__CustomPageList;
        IEnumerable的< PageInfo>页;        //只允许一个线程poplate数据
        如果(!this.cache.TryGetValue(键,出来的网页))
        {
            锁(为SyncLock)
            {
                如果(!this.cache.TryGetValue(键,出来的网页))
                {
                    // TODO:从这里数据库中取出PageInfo对象的列表。
                    页=新的List< PageInfo>()
                    {
                        新PageInfo(){ID = 1,VirtualPath =somecategory / somesubcategory /内容1},
                        新PageInfo(){ID = 2,VirtualPath =somecategory / somesubcategory /内容2},
                        新PageInfo(){ID = 3,VirtualPath =somecategory / somesubcategory / content3}
                    };                    this.cache.Set(键,页面,
                        新MemoryCacheEntryOptions()
                        {
                            优先级= CacheItemPriority.NeverRemove,
                            AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(15)
                        });
                }
            }
        }        返回页面;
    }
}

CustomRoute DI注册

  services.AddTransient< ICustomRoute,CustomRoute>();

MVC路由配置

  //添加到MVC的请求管道。
app.UseMvc(路线=>
{
    routes.Routes.Add(routes.ServiceProvider.GetService&所述; ICustomRoute>());    routes.MapRoute(
        名称:默认,
        模板:{控制器= HOME} / {行动=指数} / {?ID});    //取消注释以下行添加路由用于移植的Web API 2控制器。
    // routes.MapWebApiRoute(DefaultApi,API / {控制器} / {ID}?);
});

在情况下,重要的我使用 5测试版 DNX 4.5.1 DNX Core 5的

解决方案

As @opiants said, the problem is that you are doing nothing in your RouteAsync method.

If your intention is to end up calling a controller action method, you could use the following approach than the default MVC routes:

In your case, start by adding an IRouter as your inner target:

public class CustomRoute : ICustomRoute
{
    private readonly IMemoryCache cache;
    private readonly IRouter target;
    private object synclock = new object();

    public CustomRoute(IMemoryCache cache, IRouter target)
    {
        this.cache = cache;
        this.target = target;
    }

Then update your startup to set that target as the MvcRouteHandler, which has already been set as routes.DefaultHandler:

app.UseMvc(routes =>
{
    routes.Routes.Add(
       new CustomRoute(routes.ServiceProvider.GetRequiredService<IMemoryCache>(),
                       routes.DefaultHandler));

    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");

    // Uncomment the following line to add a route for porting Web API 2 controllers.
    // routes.MapWebApiRoute("DefaultApi", "api/{controller}/{id?}");
});

Finally, update your AsyncRoute method to call the inner IRouter, which would be the MvcRouteHandler. You can use the implementation of that method in TemplateRoute as a guide. I have quickly used this approach and modified your method as follows:

public async Task RouteAsync(RouteContext context)
{
    var requestPath = context.HttpContext.Request.Path.Value;

    if (!string.IsNullOrEmpty(requestPath) && requestPath[0] == '/')
    {
        // Trim the leading slash
        requestPath = requestPath.Substring(1);
    }

    // Get the page that matches.
    var page = GetPageList()
        .Where(x => x.VirtualPath.Equals(requestPath))
        .FirstOrDefault();

    // If we got back a null value set, that means the URI did not match
    if (page == null)
    {
        return;
    }


    //Invoke MVC controller/action
    var oldRouteData = context.RouteData;
    var newRouteData = new RouteData(oldRouteData);
    newRouteData.Routers.Add(this.target);

    // TODO: You might want to use the page object (from the database) to
    // get both the controller and action, and possibly even an area.
    // Alternatively, you could create a route for each table and hard-code
    // this information.
    newRouteData.Values["controller"] = "CustomPage";
    newRouteData.Values["action"] = "Details";

    // This will be the primary key of the database row.
    // It might be an integer or a GUID.
    newRouteData.Values["id"] = page.Id;

    try
    {
        context.RouteData = newRouteData;
        await this.target.RouteAsync(context);
    }
    finally
    {
        // Restore the original values to prevent polluting the route data.
        if (!context.IsHandled)
        {
            context.RouteData = oldRouteData;
        }
    }
}

这篇关于在ASP.NET 5 Imlementing定制IRouter(vNext)MVC 6的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-31 08:00