Asp.net mvc 如何在ASP.NET MVC路由中使用带有HttpMethodConstraint的自定义约束?
我有一个只接受此URL上帖子的控制器:Asp.net mvc 如何在ASP.NET MVC路由中使用带有HttpMethodConstraint的自定义约束?,asp.net-mvc,routing,asp.net-mvc-routing,Asp.net Mvc,Routing,Asp.net Mvc Routing,我有一个只接受此URL上帖子的控制器: POST http://server/stores/123/products 帖子的内容类型应该是application/json,因此这就是我在路由表中的内容: routes.MapRoute(null, "stores/{storeId}/products", new { controller = "Store", action = "Save" }, n
POST http://server/stores/123/products
帖子的内容类型应该是application/json
,因此这就是我在路由表中的内容:
routes.MapRoute(null,
"stores/{storeId}/products",
new { controller = "Store", action = "Save" },
new {
httpMethod = new HttpMethodConstraint("POST"),
json = new JsonConstraint()
}
);
其中JsonConstraint
是:
public class JsonConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
return httpContext.Request.ContentType == "application/json";
}
}
当我使用这条路线时,我得到一个405禁止:
不允许使用用于访问路径“/stores/123/products”的HTTP动词POST
但是,如果我删除
json=newJSONConstraint()
约束,它就可以正常工作。有人知道我做错了什么吗?我会调试JsonConstraint
并查看内容类型
无论出于何种原因,它可能不是application/json
我知道这是RFC MIME类型,但我在我的时代看到过一些其他类型(如text/x-json
),正如本文在一篇文章中提到的
另外,我从未见过ContentType约束,所以我想看看它是否有效。你有没有试过其他MIME类型,以防出现问题
最后,我将创建一个通用ContentTypeConstraint,而不是一个JsonConstraint
更新:
我在使用ContentTypeConstraint代码的路由上设计了一个快速WebRequest方法,该方法似乎工作正常
枚举
public enum ConstraintContentType
{
XML,
JSON,
}
约束类
public class ContentTypeConstraint : IRouteConstraint
{
private string mimeType;
public ContentTypeConstraint(ConstraintContentType constraintType)
{
//FYI: All this code could be redone if you used the Description attribute, and a ToDescription() method.
switch (constraintType)
{
case ConstraintContentType.JSON:
mimeType = "application/json";
break;
case ConstraintContentType.XML:
mimeType = "text/xml";
break;
default:
mimeType = "text/html";
break;
}
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
//As suggested by Eilon
if (routeDirection == RouteDirection.UrlGeneration)
return true;
return httpContext.Request.ContentType == mimeType;
}
}
使用您的示例,这将被称为:
contentType = new ContentTypeConstraint(ConstraintContentType.JSON)
这就是约束的可重用性,不仅仅是JSON。此外,如果在enum类上使用description属性,则可以取消开关大小写。我会将其放在注释中,但没有足够的空间 编写自定义约束时,检查
routeDirection
参数并确保逻辑仅在正确的时间运行非常重要
该参数告诉您是在处理传入请求时运行约束,还是在某人生成URL时运行约束(例如当他们调用Html.ActionLink
)
在您的情况下,我认为您希望将所有匹配的代码放入一个巨大的“如果”:
请发布jQuery代码片段好吗?我已经运行了一些进一步的测试,它显示ContentType显示为“application/xml”。我正在使用一个名为
REST-Client
的Firefox插件来测试它。回答得好,但我们不应该使用Accept
而不是ContentType
@Jess最初的问题特别提到了ContentType
。ContentType
表示请求主体的格式,而Accept
头表示响应主体的所需格式。在生成URL时,是否有任何特定原因默认为true?Thanks@AleksanderBethke-这取决于场景,但根据我的经验,大多数人大多数时候只希望对传入URL运行约束逻辑。对于URL生成,他们只希望所有内容都匹配,因为约束通常与URL生成没有逻辑等价物的内容(例如请求内容类型头)匹配。没有错也没有对,只有共同的模式。@Jess就是这样。可悲的是,几年前我把我的博客撤了下来,但答案的基本内容仍然有效(尽管很旧)。
public bool Match(HttpContextBase httpContext, Route route,
string parameterName, RouteValueDictionary values,
RouteDirection routeDirection)
{
if (routeDirection == RouteDirection.IncomingRequest) {
// Only check the content type for incoming requests
return httpContext.Request.ContentType == mimeType;
}
else {
// Always match when generating URLs
return true;
}
}