2015-10-05 111 views
1

我有一个OData(v3)Web API 2项目,它是另一个wcf Web服务的包装。此odata连接的预期客户端是SharePoint 2013.我在此包装器中创建CRUD操作,并注意到在要求Sharepoint删除某些内容时,会以此格式发送请求:/ Entity(Identity = XX),而不是正常/实体(XX)我工作正常。我需要能够处理该请求而不会破坏另一个请求。这是我的代码:具有可选参数的OData路由

public IHttpActionResult GetSchool([FromODataUri] int key, ODataQueryOptions<School> queryOptions) 
    { 
     // validate the query. 
     try 
     { 
      queryOptions.Validate(_validationSettings); 
     } 
     catch (ODataException ex) 
     { 
      return BadRequest(ex.Message); 
     } 
     SchoolDataSource data = new SchoolDataSource(); 
     var result = data.GetByID(key); 
     return Ok<School>(result); 
     //return StatusCode(HttpStatusCode.NotImplemented); 
    } 

这工作正常用于/学校的请求(1),但不用于/学校(ID = 1)。我曾尝试添加: [Route("Schools(ID={key}")] 这使得/ Schools(ID = 1)路线工作,但打破几乎所有其他事情(406错误)。我试图添加上述属性和 [Route("Schools({key})")],看看我是否可以让他们都工作,但它也无法正常工作。我对此很新,希望至少能有一些方向。这里是我的WebApiConfig:

 config.MapHttpAttributeRoutes(); 
     config.EnableQuerySupport(); 
     config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always; 

     // Web API configuration and services 
     ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); 
     builder.EntitySet<School>("Schools"); 
     builder.DataServiceVersion = new Version("2.0"); 
     config.Routes.MapODataRoute("odata", null, builder.GetEdmModel()); 
     // Web API routes 


     config.Routes.MapHttpRoute(
      name: "DefaultApi", 
      routeTemplate: "api/{controller}/{id}", 
      defaults: new { id = RouteParameter.Optional } 
     ); 

错误,我得到: 406,如果我有路径属性设置。 500如果我没有设置路由属性。它似乎好像我的服务不知道如何处理参数,除非我指定它,但如果我这样做,所有的调用会得到406错误。

回答

0

可能不是最好的方法,但使它与此类工作:

public class SharePointRoutingConvention : EntitySetRoutingConvention 
{ 
    public override string SelectAction(ODataPath odataPath, HttpControllerContext context, 
     ILookup<string, HttpActionDescriptor> actionMap) 
    { 
     //Gets the entity type 
     IEdmEntityType entityType = odataPath.EdmType as IEdmEntityType; 

     //makes sure the format is correct 
     if (odataPath.PathTemplate == "~/entityset/key") 
     { 
      //parses out the path segment (Identity=X) 
          KeyValuePathSegment segment = odataPath.Segments[1] as KeyValuePathSegment; 

      //Gets the verb from the request header 
      string actionName = context.Request.Method.ToString(); 

      // Add keys to route data, so they will bind to action parameters. 
      KeyValuePathSegment keyValueSegment = odataPath.Segments[1] as KeyValuePathSegment; 

      //Checks to see if the "Identity=" part is in the url 
      if (keyValueSegment.Value.Contains("Identity=")) 
      { 
       //removes the extra text 
       context.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value.Replace("Identity=", ""); 
      } 
      else 
      { 
       //parses it normally 
       context.RouteData.Values[ODataRouteConstants.Key] = keyValueSegment.Value; 
      } 

      //returns the verb 
      return actionName; 

     } 
     // Not a match. 
     return null; 
    } 
} 

,并进行更改到webapiconfig:

 var conventions = ODataRoutingConventions.CreateDefault(); 

     //adding the custom odata routing convention 
     conventions.Insert(0, new SharePointRoutingConvention()); 



    config.Routes.MapODataRoute(
      routeName: "odata", 
      routePrefix: null,//this is so that you can type the base url and get metadata back (http://localhost/) 
      model: builder.GetEdmModel(), 
      pathHandler: new DefaultODataPathHandler(), 
      routingConventions: conventions //this assigns the conventions to the route 
      );