2014-11-26 2 views
3

Я создаю образец из двух образцов OData Web API, каждый из которых отлично работает как отдельный проект. Но когда я добавляю второй класс ODataController, тогда сайт больше не работает, жалуясь на шаблоны пути OData, которые работали ранее. Вот более подробная информация:Добавление нового контроллера OData не удается из-за существующего контроллера

Следующее действие отлично работает до тех пор, как его контроллер (ProductsController) является единственным контроллером:

[HttpGet] 
[ODataRoute("GetSalesTaxRate(state={state})")] 
public IHttpActionResult GetSalesTaxRate([FromODataUri] string state) 
{ 
    return Ok(GetRate(state)); 
} 

Теперь добавьте новый контроллер (MoviesController) с несколькими действиями.

Выражает класс Owin запуска, так это выглядит следующим образом:

public void Configuration(IAppBuilder builder) 
{ 
    var config = new HttpConfiguration(); 

    config.MapODataServiceRoute(routeName: "functions route", routePrefix: "functions", model: FunctionStartup.GetEdmModel()); 
    config.MapODataServiceRoute(routeName: "actions route", routePrefix: "actions", model: ActionStartup.GetEdmModel()); 

    builder.UseWebApi(config); 
} 

Однако, когда я пытаюсь выполнить веб-запрос (URLBase/функция/$ метаданных), я получаю следующее сообщение об ошибке:

System.InvalidOperationExceptionThe path template 'GetSalesTaxRate(state={state})' on the action 'GetSalesTaxRate' in controller 'Products' is not a valid OData path template. Resource not found for the segment 'GetSalesTaxRate'.

Контроллеры отображаются на разные маршруты («функции» и «действия»). Может быть, проблема в том, что каждый маршрут сопоставляется с его собственным EdmModel?

ОБНОВЛЕНИЕ. Я проверил, что могу добавить больше контроллеров, если они относятся к одной и той же модели EDM. Но как только я представляю вторую модель (и ссылаюсь на нее с MapODataServiceRoute), тогда вся услуга ломается. Есть ли способ обхода нескольких моделей?

ОБНОВЛЕНИЕ 2. Если я подклассом DefaultHttpControllerTypeResolver и включаю только один контроллер (любой из них), то также работает отлично. Но я все еще озадачен тем, почему несколько контроллеров, использующих разные модели, терпят неудачу.

ответ

5

По умолчанию, когда атрибуты маршрутизации атрибутов карты OData, логика по умолчанию для контроллера HTTP-контроллера IHttpControllerSelector использует функцию HttpConfiguration DefaultAssembloesResolver, которая будет искать все типы контроллеров в домене приложения. Объем может быть сведен к тому, что контроллеры относятся к модели.

Мы можем настроить методы расширения MapODataServiceRoute. Некоторые фрагменты кода:

public class Startup 
{ 
    public void Configuration(IAppBuilder builder) 
    { 
     var config = new HttpConfiguration(); 

     config.CustomMapODataServiceRoute(routeName: "functions route", routePrefix: "functions", 
      model: FunctionStartup.GetEdmModel(), 
      controllers: new[] { typeof(ProductsController) }); 
     config.CustomMapODataServiceRoute(routeName: "actions route", routePrefix: "actions", 
      model: ActionStartup.GetEdmModel(), 
      controllers: new[] { typeof(MoviesController) }); 

     config.EnsureInitialized(); 

     builder.UseWebApi(config); 
    } 
} 

public class CustomAttributeRoutingConvention : AttributeRoutingConvention 
{ 
    private readonly List<Type> _controllers = new List<Type> { typeof(MetadataController) }; 

    public CustomAttributeRoutingConvention(IEdmModel model, HttpConfiguration configuration, IEnumerable<Type> controllers) 
     : base(model, configuration) 
    { 
     _controllers.AddRange(controllers); 
    } 

    public override bool ShouldMapController(HttpControllerDescriptor controller) 
    { 

     return _controllers.Contains(controller.ControllerType); 
    } 
} 

public static class HttpConfigExt 
{ 
    public static ODataRoute CustomMapODataServiceRoute(this HttpConfiguration configuration, string routeName, 
     string routePrefix, IEdmModel model, IEnumerable<Type> controllers) 
    { 
     var routingConventions = ODataRoutingConventions.CreateDefault(); 
     routingConventions.Insert(0, new CustomAttributeRoutingConvention(model, configuration, controllers)); 
     return configuration.MapODataServiceRoute(routeName, routePrefix, model, new DefaultODataPathHandler(), 
      routingConventions); 
    } 
} 
+0

Спасибо Congyong, это то, чего мне не хватало! –

+0

Этот ответ спас мою жизнь !!! – Rahul

Смежные вопросы