MVC 6 ile çalışmak için this sample RouteBase implementation dönüştürmeyi deniyorum. the example in the Routing project'u izleyerek çoğunu çözdüm, ancak nasıl geri döneceğimi anladım Eşzamansız Task
yöntemden. Aslına bakarsan gerçekten umursamıyorum (bu cevabı sağlayabilecek herkese tezahürat edin), şimdilik sadece işe yaramak istiyorum.Özel bir IRouter'ı ASP.NET 5 (vNext) içinde gerçekleştirme MVC 6
Giden yolları çalıştırıyorum (ActionLink
, rota değerlerini girdiğimde iyi çalışıyor). Sorun, RouteAsync
yöntemiyle ilgilidir.
public 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)
{
var routeData = new RouteData();
// This doesn't work
//var routeData = new RouteData(context.RouteData);
// This doesn't work
//routeData.Routers.Add(this);
// This doesn't work
//routeData.Routers.Add(new MvcRouteHandler());
// 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.
routeData.Values["controller"] = "CustomPage";
routeData.Values["action"] = "Details";
// This will be the primary key of the database row.
// It might be an integer or a GUID.
routeData.Values["id"] = page.Id;
context.RouteData = routeData;
// When there is a match, the code executes to here
context.IsHandled = true;
// This test works
//await context.HttpContext.Response.WriteAsync("Hello there");
// This doesn't work
//return Task.FromResult(routeData);
// This doesn't work
//return Task.FromResult(context);
}
// This satisfies the return statement, but
// I'm not sure it is the right thing to return.
return Task.FromResult(0);
}
Tüm yöntem, bir eşleşme olduğunda sonuna kadar çalışır. Ancak, yürütülürken, olması gerektiği gibi, CustomPage
denetleyicisinin Details
yöntemini çağırmaz. Sadece tarayıcıda boş bir beyaz sayfa alıyorum. this post yapılan ve boş sayfaya Hello there
yazar gibi
WriteAsync
hattını eklendi, ancak MVC (bu aksamadan çalıştı önceki sürümlerinde) benim denetleyicisi aramıyor neden anlayamıyorum. Ne yazık ki, bu gönderi, bir
IRouter
veya
INamedRouter
'un nasıl uygulanacağı haricinde, yönlendirmenin her bölümünü kapsıyordu.
RouteAsync
yöntem işlevini nasıl yapabilirim?
Bütün CustomRoute Uygulama
services.AddTransient<ICustomRoute, CustomRoute>();
MVC Rota Yapılandırma durumda
// Add MVC to the request pipeline.
app.UseMvc(routes =>
{
routes.Routes.Add(routes.ServiceProvider.GetService<ICustomRoute>());
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?}");
});
ben Beta 5
, DNX 4.5.1
ve DNX Core 5
kullanıyorum konularda
using Microsoft.AspNet.Routing;
using Microsoft.Framework.Caching.Memory;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public class PageInfo
{
// VirtualPath should not have a leading slash
// example: events/conventions/mycon
public string VirtualPath { get; set; }
public int Id { get; set; }
}
public interface ICustomRoute : IRouter
{ }
public class CustomRoute : ICustomRoute
{
private readonly IMemoryCache cache;
private object synclock = new object();
public CustomRoute(IMemoryCache cache)
{
this.cache = cache;
}
public 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)
{
var routeData = new RouteData();
// 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.
routeData.Values["controller"] = "CustomPage";
routeData.Values["action"] = "Details";
// This will be the primary key of the database row.
// It might be an integer or a GUID.
routeData.Values["id"] = page.Id;
context.RouteData = routeData;
context.IsHandled = true;
}
return Task.FromResult(0);
}
public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
VirtualPathData result = null;
PageInfo page = null;
// Get all of the pages from the cache.
var pages = GetPageList();
if (TryFindMatch(pages, context.Values, out page))
{
result = new VirtualPathData(this, page.VirtualPath);
context.IsBound = true;
}
return result;
}
private bool TryFindMatch(IEnumerable<PageInfo> pages, IDictionary<string, object> values, out PageInfo page)
{
page = null;
int id;
object idObj;
object controller;
object action;
if (!values.TryGetValue("id", out idObj))
{
return false;
}
id = Convert.ToInt32(idObj);
values.TryGetValue("controller", out controller);
values.TryGetValue("action", out action);
// The logic here should be the inverse of the logic in
// GetRouteData(). So, we match the same controller, action, and id.
// If we had additional route values there, we would take them all
// into consideration during this step.
if (action.Equals("Details") && controller.Equals("CustomPage"))
{
page = pages
.Where(x => x.Id.Equals(id))
.FirstOrDefault();
if (page != null)
{
return true;
}
}
return false;
}
private IEnumerable<PageInfo> GetPageList()
{
string key = "__CustomPageList";
IEnumerable<PageInfo> pages;
// Only allow one thread to poplate the data
if (!this.cache.TryGetValue(key, out pages))
{
lock (synclock)
{
if (!this.cache.TryGetValue(key, out pages))
{
// TODO: Retrieve the list of PageInfo objects from the database here.
pages = new List<PageInfo>()
{
new PageInfo() { Id = 1, VirtualPath = "somecategory/somesubcategory/content1" },
new PageInfo() { Id = 2, VirtualPath = "somecategory/somesubcategory/content2" },
new PageInfo() { Id = 3, VirtualPath = "somecategory/somesubcategory/content3" }
};
this.cache.Set(key, pages,
new MemoryCacheEntryOptions()
{
Priority = CacheItemPriority.NeverRemove,
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(15)
});
}
}
}
return pages;
}
}
CustomRoute DI Kaydı.
Çözüm Ben burada öğrenilen bilgilere dayalı URL 2 yönlü haritalama in this answer için basit birincil anahtar için kullanılabilecek bir jenerik çözüm yarattı. Birincil anahtarın denetleyicisi, eylemi, veri sağlayıcısı ve veri türü, MVC 6 yönlendirmesine bağlanırken belirtilebilir.
Evet, içsel bir Kızılötesi'ye sahip olmayı düşündüm ama buna ihtiyacın olduğunu düşünmüyorum. Context.IsHandled öğesinin false değerine ayarlanması ve erken dönmesi, bir sonraki kayıtlı IRouter'a geçmesine ve sonuçta route'lara geri dönmesine neden olur.DefaultHandler (MvcRouteHandler olan) – Dealdiane
Hiçbir yol eşleşme yoksa DefaultHandler'ın kullanılacağından emin misiniz? ? Kod bakmak için sadece ['MapRoute'] (https://github.com/aspnet/Routing/blob/dev/src/Microsoft.AspNet.Routing/RouteBuilderExtensions.cs) uzantı yöntemi için kullanıldığı görülüyor MVC yolları bir iç MvcRouteHandler –
ile TemplateRoute kullanılarak eklenir. Ayrıca kontrol edin ['RouteBuilder.Build'] (https://github.com/aspnet/Routing/blob/dev/src/Microsoft.AspNet.Routing/RouteBuilder.cs) Sadece tanımlanmış olan her yolu ekleyecektir, ancak varsayılan işleyici değil –