asp.net-mvc – 有没有办法让RoutePrefix以可选参数开头?
我想用这些URL到达Bikes控制器:
/bikes // (default path for US) /ca/bikes // (path for Canada) 实现这一目标的一种方法是每个Action使用多个Route属性: [Route("bikes")] [Route("{country}/bikes")] public ActionResult Index() 为了保持DRY,我更喜欢使用RoutePrefix,但不允许使用多个路由前缀: [RoutePrefix("bikes")] [RoutePrefix("{country}/bikes")] // <-- Error: Duplicate 'RoutePrefix' attribute public class BikesController : BaseController [Route("")] public ActionResult Index() 我试过使用这个Route Prefix: [RoutePrefix("{country}/bikes")] public class BikesController : BaseController 结果:/ ca /?? bikes工作,/自行车404s. 我试过让国家选择: [RoutePrefix("{country?}/bikes")] public class BikesController : BaseController 相同的结果:/ ca /?? bikes工作,/自行车404s. 我试过给国家一个默认值: [RoutePrefix("{country=us}/bikes")] public class BikesController : BaseController 相同的结果:/ ca /?? bikes工作,/自行车404s. 有没有其他方法可以使用属性路由实现我的目标? 我正在使用Microsoft.AspNet.Mvc 5.2.2. 仅供参考:这些是简化示例 – 实际代码具有{country}值的IRouteConstraint,例如: [Route("{country:countrycode}/bikes")] 解决方法
我参加聚会有点晚了,但我有一个解决这个问题的工作方案.请在这个问题
here找到我的详细博客文章
我在下面写下摘要 您需要创建2个文件,如下所示 > _3bTechTalkMultiplePrefixDirectRouteProvider.cs using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Web.Http.Controllers; using System.Web.Http.Routing; namespace _3bTechTalk.MultipleRoutePrefixAttributes { public class _3bTechTalkMultiplePrefixDirectRouteProvider: DefaultDirectRouteProvider { protected override IReadOnlyList GetActionDirectRoutes(HttpActionDescriptor actionDescriptor,IReadOnlyList factories,IInlineConstraintResolver constraintResolver) { return CreateRouteEntries(GetRoutePrefixes(actionDescriptor.ControllerDescriptor),factories,new [] { actionDescriptor },constraintResolver,true); } protected override IReadOnlyList GetControllerDirectRoutes(HttpControllerDescriptor controllerDescriptor,IReadOnlyList actionDescriptors,IInlineConstraintResolver constraintResolver) { return CreateRouteEntries(GetRoutePrefixes(controllerDescriptor),actionDescriptors,false); } private IEnumerable GetRoutePrefixes(HttpControllerDescriptor controllerDescriptor) { Collection attributes = controllerDescriptor.GetCustomAttributes (false); if (attributes == null) return new string[] { null }; var prefixes = new List (); foreach(var attribute in attributes) { if (attribute == null) continue; string prefix = attribute.Prefix; if (prefix == null) throw new InvalidOperationException("Prefix can not be null. Controller: " + controllerDescriptor.ControllerType.FullName); if (prefix.EndsWith("/",StringComparison.Ordinal)) throw new InvalidOperationException("Invalid prefix" + prefix + " in " + controllerDescriptor.ControllerName); prefixes.Add(prefix); } if (prefixes.Count == 0) prefixes.Add(null); return prefixes; } private IReadOnlyList CreateRouteEntries(IEnumerable prefixes,IReadOnlyCollection factories,IReadOnlyCollection actions,IInlineConstraintResolver constraintResolver,bool targetIsAction) { var entries = new List (); foreach(var prefix in prefixes) { foreach(IDirectRouteFactory factory in factories) { RouteEntry entry = CreateRouteEntry(prefix,factory,actions,targetIsAction); entries.Add(entry); } } return entries; } private static RouteEntry CreateRouteEntry(string prefix,IDirectRouteFactory factory,bool targetIsAction) { DirectRouteFactoryContext context = new DirectRouteFactoryContext(prefix,targetIsAction); RouteEntry entry = factory.CreateRoute(context); ValidateRouteEntry(entry); return entry; } private static void ValidateRouteEntry(RouteEntry routeEntry) { if (routeEntry == null) throw new ArgumentNullException("routeEntry"); var route = routeEntry.Route; if (route.Handler != null) throw new InvalidOperationException("Direct route handler is not supported"); } } } > 3bTechTalkRoutePrefix.cs using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Http; namespace _3bTechTalk.MultipleRoutePrefixAttributes { [AttributeUsage(AttributeTargets.Class,AllowMultiple = true,Inherited = true)] public class _3bTechTalkRoutePrefix : RoutePrefixAttribute { public int Order { get; set; } public _3bTechTalkRoutePrefix(string prefix) : this(prefix,0) { } public _3bTechTalkRoutePrefix(string prefix,int order) : base(prefix) { Order = order; } } } 完成后,打开WebApiConfig.cs并在给定行下面添加此项 config.MapHttpAttributeRoutes(new _3bTechTalkMultiplePrefixDirectRouteProvider()); 就是这样,现在您可以在controller中添加多个路由前缀.示例如下 [_3bTechTalkRoutePrefix("api/Car",Order = 1)] [_3bTechTalkRoutePrefix("{CountryCode}/api/Car",Order = 2)] public class CarController: ApiController { [Route("Get")] public IHttpActionResult Get() { return Ok(new { Id = 1,Name = "Honda Accord" }); } } 我上传了一个有效的解决方案here 快乐编码:) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net – OData和区分大小写
- 在asp.net中制作某些页面的最佳方法是什么?需要
- 你如何获得asp.net控件的自动生成的name属性?
- 实体框架 – 使用实体框架数据模型添加验证属性
- asp.net-mvc – ASP.Net MVC和jQuery表单插件上传
- asp.net-mvc – formcollection只保存所选的html
- asp.net-mvc-4 – htmlHelper与局部视图
- asp.net-mvc-3 – 如何从控制器外部访问登录用户
- asp.net-mvc-4 – bundle(Sytem.Web.Optimizatio
- asp.net-mvc-3 – IIS7中的NLog在发布模式下失败