我有一个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" });
所以在Nutshell中,我有一个匹配某些HTTP动词的路由,如GET和POST,但是在其他HTTP动词上,如PUT和DELETE,它应该返回一个特定的错误。
我的默认路线是404。
如果我删除“BadFoo”路由,则针对端点/ {id}的PUT返回404,因为其他路由都不匹配,因此它将转到我的NotFound路由。
问题是,我有很多路线,比如Get和Post,我有一个HttpMethodConstraint,我必须创建一条像BadFoo路线一样的路线,只是为了在路线上找到正确的匹配但不在方法上,这会不必要地炸毁我的路由。
如何设置仅使用Get,Post和NotFound路由的路由,同时仍然区分未找到的HTTP 404(=无效的URL)和不允许的HTTP 405方法(=有效的URL,错误的HTTP方法)?
答案 0 :(得分:4)
您可以使用自定义ControllerActionInvoker
和ActionMethodSelector
属性(例如[HttpGet]
,[HttpPost]
等)将HTTP方法验证委派给MVC运行时,而不是使用路径约束。 :
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;
}
}
}
请注意我的上一条评论“发现的操作,方法不允许?”,我将此写为一个问题,因为可能存在与HTTP方法验证无关的ActionMethodSelector
个属性...