2017-08-08 149 views
0

我們有以下的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程序集,任何幫助非常感謝。

感謝, 裏克

回答

0

更新: 我設法得到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) 
{ 
}