我有一个 ASP.net MVC 3 站点,其路由如下:
routes.MapRoute("Get", "endpoint/{id}",
new { Controller = "Foo", action = "GetFoo" },
new { httpMethod = new HttpMethodConstraint("GET") });
routes.MapRoute("Post", "endpoint/{id}",
new { Controller = "Foo", action = "NewFoo" },
new { httpMethod = new HttpMethodConstraint("POST") });
routes.MapRoute("BadFoo", "endpoint/{id}",
new { Controller = "Error", action = "MethodNotAllowed" });
routes.MapRoute("NotFound", "",
new { controller = "Error", action = "NotFound" });
因此,简而言之,我有一个与某些 HTTP 动词(如 GET 和 POST)匹配的路由,但在其他 HTTP 动词(如 PUT 和 DELETE)上它应该返回一个特定的错误。
我的默认路由是 404。
如果我删除“BadFoo”路由,那么针对端点/{id} 的 PUT 将返回 404,因为没有其他路由匹配,所以它转到我的 NotFound 路由。
问题是,我有很多像 Get 和 Post 这样的路由,我有一个 HttpMethodConstraint,我必须创建一个像 BadFoo 路由这样的路由,只是为了在路由字符串上而不是在 Method 上找到正确的匹配,这很糟糕不必要地增加我的路由。
如何仅使用 Get、Post 和 NotFound 路由设置路由,同时仍然区分未找到 HTTP 404(=无效 URL)和不允许 HTTP 405 方法(=有效 URL,错误 HTTP 方法)?
最佳答案
您可以使用自定义 ControllerActionInvoker
将 HTTP 方法验证委托(delegate)给 MVC 运行时,而不是使用路由约束。和 ActionMethodSelector
[HttpGet]
等属性, [HttpPost]
, ETC。:
using System;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MvcApplication6.Controllers {
public class HomeController : Controller {
protected override IActionInvoker CreateActionInvoker() {
return new CustomActionInvoker();
}
[HttpGet]
public ActionResult Index() {
return Content("GET");
}
[HttpPost]
public ActionResult Index(string foo) {
return Content("POST");
}
}
class CustomActionInvoker : ControllerActionInvoker {
protected override ActionDescriptor FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, string actionName) {
// Find action, use selector attributes
var action = base.FindAction(controllerContext, controllerDescriptor, actionName);
if (action == null) {
// Find action, ignore selector attributes
var action2 = controllerDescriptor
.GetCanonicalActions()
.FirstOrDefault(a => a.ActionName.Equals(actionName, StringComparison.OrdinalIgnoreCase));
if (action2 != null) {
// Action found, Method Not Allowed ?
throw new HttpException(405, "Method Not Allowed");
}
}
return action;
}
}
}
请注意我的最后一条评论“找到的操作,不允许的方法?”,我将其写为一个问题,因为可以有
ActionMethodSelector
与 HTTP 方法验证无关的属性...
关于.net - 与另一个路由匹配的路由,忽略 HttpMethodConstraint?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5160860/