的OData V4.0 - PUT,PATCH,DELETE返回404
问题描述:
我们有以下的NuGet包一个C#.NET的Web API项目,amoungst人:的OData V4.0 - PUT,PATCH,DELETE返回404
- MVC 5.2.3
- 微软ASP.NET网页API 2.2的OData V4.0(6.0.0版)
- Microsoft.AspNet.OData.Versioning(2.1.0版本)
在IIS中,PUT,PATCH和DELETE动词已为ExtensionlessUrl启用 - applicationhost.config文件中的集成-4.0。
以下是
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
System.Web.Routing.RouteTable.Routes.Ignore("robots.txt");
System.Web.Routing.RouteTable.Routes.Ignore("{resource}.axd/{*pathInfo}");
// http://weblogs.asp.net/imranbaloch/handling-http-404-error-in-asp-net-web-api
System.Web.Routing.RouteTable.Routes.MapHttpRoute(
name: "Error404",
routeTemplate: "{*url}",
defaults: new { controller = "Error", action = "Handle404" }
);
config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
// NOTE: Method below removed and functionality to replace it not working due to bug https://github.com/OData/WebApi/issues/812
//config.EnableCaseInsensitive(caseInsensitive: true);
// http://stackoverflow.com/questions/30987439/elmah-axd-on-webapi-2-2-no-http-resource-was-found
config.Routes.MapHttpRoute(
"AXD", "{resource}.axd/{*pathInfo}", null, null,
new StopRoutingHandler());
// we will use attribute routing
config.MapHttpAttributeRoutes();
// set default page size and total number of rows to return from query
config.AddODataQueryFilter(new EnableQueryAttribute
{
PageSize = ConfigurationWrapper.Singleton.ODataPageSize,
MaxTop = ConfigurationWrapper.Singleton.ODataMaxTop,
MaxExpansionDepth = ConfigurationWrapper.Singleton.ODataMaxExpansionDepth
});
config.AddApiVersioning(o =>
{
o.AssumeDefaultVersionWhenUnspecified = true;
o.ReportApiVersions = true;
});
// http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-routing-conventions
// Create the default collection of built-in conventions
IList<IODataRoutingConvention> conventions = ODataRoutingConventions.CreateDefault();
// Insert the custom convention at the start of the collection; caters for ~/entityset/key/navigation/key
conventions.Insert(0, new NavigationIndexRoutingConvention());
config.MapODataServiceRoute(
routeName: "odata",
routePrefix: null,
model: EdmModelBuilder.GetEdmModel(),
pathHandler: new DefaultODataPathHandler(),
routingConventions: conventions,
batchHandler: new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer));
//config.MapVersionedODataRoutes(
//routeName: "odata",
//routePrefix: null,
//models: EdmModelBuilder.GetEdmModels(config),
//pathHandler: new DefaultODataPathHandler(),
//routingConventions: GetConventions());
// EnableDependencyInjection is required if you want to have OData routes and custom routes together in a controller
config.EnableDependencyInjection();
config.Count().Filter().OrderBy().Expand().Select().MaxTop(null); //new line
config.Formatters.Remove(config.Formatters.XmlFormatter);
// The XML formatter is not well enough supported by OData v4.0 (apparently works with OData v3.0), reverting to JSON only
config.Formatters.InsertRange(0, ODataMediaTypeFormatters.Create());
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
/* ReferenceLoopHandling.Ignore: Json.NET will ignore objects in reference loops and not serialize them. The first time an object is encountered
* it will be serialized as usual but if the object is encountered as a child object of itself the serializer will skip serializing it.
*/
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
config.Filters.AddRange(new List<IFilter>
{
new ForfrontAuthenticationAttribute(), // custom
new RateLimitAttribute(), // custom
new RequestAuditAttribute(), // custom
new SuppressResponseCodeSuccessAttribute(), // custom
new ExceptionHandlingAttribute() // custom
});
// http://weblogs.asp.net/imranbaloch/handling-http-404-error-in-asp-net-web-api
config.Services.Replace(typeof(IHttpControllerSelector), new HttpNotFoundAwareDefaultHttpControllerSelector(config));
config.Services.Replace(typeof(IHttpActionSelector), new HttpNotFoundAwareControllerActionSelector());
config.EnsureInitialized();
}
}
控制器动作我想呼叫被定义为WebApiConfig.cs:
[ApiVersion("1.0")]
[ODataRoutePrefix("MicrosoftDynamicsContactFieldMappings")]
[ControllerName("MicrosoftDynamicsContactFieldMappings")]
public class MicrosoftDynamicsContactFieldMappingsController : ForfrontODataController
{
// DELETE: MicrosoftDynamicsContactFieldMappings(5)
/// <summary>
/// We don't really delete records, but update, user doesn't need to know internal workings.
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
[AcceptVerbs("DELETE")]
public IHttpActionResult Delete([FromODataUri] int key)
{
// this is not being called
}
}
在Fiddler中REST API请求的格式为:
DELETE http://dev2.e-shot.local/MicrosoftDynamicsContactFieldMappings(11)
HTTP/1.1
Host: dev2.e-shot.local
User-Agent: Fiddler
Authorization: Token [token value goes here]
Accept-Language: en-GB
当对DELETE(PATCH或PUT)进行请求时,返回404。看起来OData路由不被考虑。
希望不必调试OData程序集,任何帮助非常感谢。
感谢, 里克
答
更新: 我设法得到DELETE,PATCH和PUT动词使用属性路由和避免的OData路由约定的工作。
[AcceptVerbs("DELETE")]
[Route("MicrosoftDynamicsContactFieldMappings({key})")]
public IHttpActionResult Delete([FromUri] int key)
{
}
[AcceptVerbs("PATCH", "MERGE")]
[Route("MicrosoftDynamicsContactFieldMappings({key})")]
public IHttpActionResult Patch([FromODataUri] int key,
Delta<MicrosoftDynamicsContactFieldMapping> item)
{
}