2016-12-15 123 views
2

我有ASP.NET的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为空,我在我的方法中得到了NullReferenceException

有没有办法告诉WebApi总是使用new TestRequest()的实例作为方法参数,即使查询字符串为空?

+0

没有自动的方式来做到这一点,而无需创建特定于web api的自定义绑定。如果您想在方法签名中使用'default(TestRequest)',请参阅http://stackoverflow.com/a/4066357/1260204。 – 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

使用空是虽然没有正确的设计聪明的最简单方法。

否则,您可以使用自定义模型联编程序为您的TestRequest类型创建自定义行为。你可以找到相同的例子。

+0

你能否指出创建这样一个活页夹的任何例子,它将为传递到WebAPI方法的任何类型调用'new TParam()',而不仅仅是'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