【问题标题】:OData Routing with Optional Parameter带有可选参数的 OData 路由
【发布时间】:2015-10-05 18:12:49
【问题描述】:

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

    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);
    }

这适用于 /Schools(1) 的请求,但不适用于 /Schools(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 错误。

【问题讨论】:

    标签: wcf sharepoint asp.net-web-api odata asp.net-web-api2


    【解决方案1】:

    可能不是最好的方法,但使它适用于此类:

    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
                );
    

    【讨论】:

      猜你喜欢
      • 2023-03-03
      • 2016-10-12
      • 2011-01-09
      • 2013-09-10
      • 2016-08-01
      • 2013-12-07
      • 2018-04-06
      • 1970-01-01
      相关资源
      最近更新 更多