2016-12-15 4 views
2

У меня есть метод действий ASP.NET WebAPI, который выглядит следующим образом:Значения по умолчанию для метода WebAPI параметры

[HttpGet] 
public HttpResponseMessage Test([FromUri] TestRequest request) 
{ 
    request.Process(); 
    return new HttpResponseMessage(HttpStatusCode.OK); 
} 

public class TestRequest 
{ 
    public string TestParam1 { get; set; } 
    public string TestParam2 { get; set; } 

    public void Process() 
    { 
     // do work 
    } 
} 

Это хорошо работает, если запрос URL указанные имеют параметры, например, http://localhost/test?TestParam1=1. Но когда строка запроса пуста, request param имеет значение null, и я получаю NullReferenceException в моем методе.

Есть ли способ сказать WebApi всегда использовать экземпляр new TestRequest() в качестве параметра метода, даже если строка запроса пуста?

+0

Нет автоматического способа сделать это без создания настраиваемого связующего, специфичного для веб-api. См. Также http://stackoverflow.com/a/4066357/1260204, если вы подумывали использовать 'default (TestRequest)' в вашей сигнатуре метода. – Igor

ответ

1
  1. Определение пользовательской модели связующего:

    public class TestRequestModelBinder : System.Web.Http.ModelBinding.IModelBinder 
    { 
        public bool BindModel(HttpActionContext actionContext, 
              System.Web.Http.ModelBinding.ModelBindingContext bindingContext) 
        { 
         if (bindingContext.ModelType != typeof(TestRequest)) return false; 
    
         bindingContext.Model = new TestRequest(); 
    
         var parameters = actionContext.Request.RequestUri.ParseQueryString(); 
    
         typeof(TestRequest) 
          .GetProperties() 
          .Select(property => property.Name) 
          .ToList() 
          .ForEach(propertyName => 
          { 
           var parameterValue = parameters[propertyName]; 
    
           if(parameterValue == null) return;  
    
           typeof(TestRequest).GetProperty(propertyName).SetValue(bindingContext.Model, parameterValue); 
          }); 
    
         return bindingContext.ModelState.IsValid; 
        } 
    } 
    
  2. Использование:

    [HttpGet] 
    public HttpResponseMessage Test([System.Web.Http.ModelBinding.ModelBinder(typeof(TestRequestModelBinder))] TestRequest request) 
    { 
        // your code 
    } 
    
0

Вам просто нужно проверить null:

[HttpGet] 
public HttpResponseMessage Test([FromUri] TestRequest request) 
{ 
    if (request == null) 
     request = new TestRequest(); 
    var result = request.Process(); 
+0

Это, безусловно, будет работать, но я ищу способ инструктировать фреймворк для вызова 'new TestRequest()'. Я бы не хотел иметь нулевые проверки во всех моих API-методах. –

0

Использование Null это самый простой способ, хотя и не прямо дизайн мудрым.

Кроме того, вы можете создать собственное поведение, используя настраиваемое связующее устройство для вашего типа TestRequest. Вы можете найти множество примеров для одного и того же.

+0

Можете ли вы указать на любой пример создания такого связующего, который будет вызывать 'новый TParam()' для любого типа, переданного в метод WebAPI, а не только для 'TestRequest'? –

0

Можно только установить значения по умолчанию для констант в списке параметров, чтобы он не работал так, как вы этого хотите.

Если у вас есть метод подпись, как это вы можете установить значение по умолчанию «КИ», например

public HttpResponseMessage Test(string request = "ok") 

В вашем сценарии, ИМО, лучший способ, чтобы установить значение параметра в качестве обнуляемых и проверок против этого в контроллере

[HttpGet] 
public HttpResponseMessage Test([FromUri] TestRequest? request) 
{ 
    if(request.HasValue) 
    { 
     //Do your thing 
    } 
} 
0

Ответ Andriy Tolstoy помог, мне пришлось изменить его немного, хотя, чтобы получить некоторые из моих целочисленных свойств работать.

Вот обновленный ModelBinder я использовал, в случае, если это помогает кому-то:

public class TestRequestModelBinder : IModelBinder 
{ 
    public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext) 
    { 
     if (bindingContext.ModelType != typeof(TestRequest)) return false; 

     bindingContext.Model = new TestRequest(); 
     var parameters = actionContext.Request.RequestUri.ParseQueryString(); 

     typeof(TestRequest) 
      .GetProperties() 
      .ToList() 
      .ForEach(property => 
      { 
       var parameterValue = parameters[property.Name]; 
       if (parameterValue == null) return; 
       typeof(TestRequest).GetProperty(property.Name).SetValue(bindingContext.Model, Convert.ChangeType(parameterValue, property.PropertyType)); 
      }); 
     return bindingContext.ModelState.IsValid; 
    } 
} 

Основное изменение является приведение значения к исходному PropertyType имущества.

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