2015-10-19 48 views
0

在Web Api 2中,控制器上的一个方法可以有许多从URI提供的参数,如果字符串无法转换为int,则将字符串转换为int并返回自动Web错误消息。Web Api 2:自定义参数验证(typeconverter)

我想对自定义类型做同样的事情。我创建了一个仅包含DateTime对象的类,并且想将Web URI字符串参数自定义转换为此DateTime对象。为此我实现了一个TypeConverter。有用。我的问题是,如果我给它一个错误的日期字符串,我没有网络错误,我的方法得到一个空指针。这是我的模型的类型转换器:

[TypeConverter(typeof(DkDateTimeConverter))] 
public class DkDateTime 
{ 
    private static readonly ILog log4 = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 

    public DateTime dkDateTime; 

    public static bool TryParse(string s, out DkDateTime result) 
    { 
     log4.Debug("TryParse"); 
     result = null; 

     var culture = new CultureInfo("da"); 
     try 
     { 
      result = new DkDateTime() 
      { 
       dkDateTime = DateTime.ParseExact(s, "dd-MM-yyyy HH:mm:ss", culture) 
      }; 
      return true; 
     } 
     catch 
     { 
      return false; 
     } 
    } 
} 

class DkDateTimeConverter : TypeConverter 
{ 
    private static readonly ILog log4 = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 
    { 
     log4.Debug("CanConvertFrom"); 
     if (sourceType == typeof(string)) 
     { 
      return true; 
     } 
     return base.CanConvertFrom(context, sourceType); 
    } 

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) 
    { 
     log4.Debug("ConvertFrom"); 
     if (value is string) 
     { 
      DkDateTime dkDateTime; 
      if (DkDateTime.TryParse((string)value, out dkDateTime)) 
      { 
       return dkDateTime; 
      } 
      else 
      { 
       log4.Debug("Exception"); 
       throw new NotSupportedException(); 
      } 
     } 
     return base.ConvertFrom(context, culture, value); 
    } 
} 

我的控制器具有这种方法为切入点:

public IHttpActionResult Get(Guid messageid, int statuscode, DkDateTime sentdate, DkDateTime donedate) 

我的印象是,如果ConvertFrom导致异常,这将是通过网页API反映并且网络错误消息将被发回给调用者。如果我给“2A”为的StatusCode,我得到一个网络错误这样的:

<Error> 
<Message>The request is invalid.</Message> 
</Error> 

如何触发与我的类型转换器相同的错误消息?或许一个typeconverter不能帮助,但我应该看看哪种方式?

回答

2

你在做什么是正确的,它是由设计。想想你会从messageid参数中的无效Guid期望什么。那里同样的事情发生。路线不匹配或您收到无效请求。为了更好地控制模型状态验证&错误消息,您应该继承IModelBinder并构建自定义DkDateTimeModelBinder

检查这个帖子:Parameter Binding in ASP.NET Web API

更新与例如

public class DkDateTime 
{ 
    public DateTime dkDateTime; 

    public static bool TryParse(string s, out DkDateTime result) { 
     result = null; 
     var dateTime = default(DateTime); 
     if (DateTime.TryParseExact(s, "dd-MM-yyyy HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dateTime)) { 
      result = new DkDateTime { dkDateTime = dateTime }; 
      return true; 
     } 
     return false; 
    } 
} 

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

     ValueProviderResult val = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 

     if (val == null) { 
      return false; 
     } 

     string key = val.RawValue as string; 
     if (key == null) { 
      bindingContext.ModelState.AddModelError(
       bindingContext.ModelName, "Wrong value type"); 
      return false; 
     } 

     DkDateTime result; 
     if (DkDateTime.TryParse(key, out result)) { 
      bindingContext.Model = result; 
      return true; 
     } 

     bindingContext.ModelState.AddModelError(
      bindingContext.ModelName, "Cannot convert value to DkDateTime"); 
     return false; 
    } 
} 

然后在控制器:

public class ExampleController : ApiController 
{ 
    [Route("test")] 
    public async Task<IHttpActionResult> GetDk([ModelBinder(typeof(DkDateTimeModelBinder))]DkDateTime sendDate) { 
     if (!ModelState.IsValid) { 
      return BadRequest(ModelState); 
     } 
     return Ok(sendDate); 
    } 
} 

现在,当我与URL http://localhost:4814/example/test?senddate=dsfasdafsd测试,我得到以下

状态400错误的请求预期respose

{ 
    "Message": "The request is invalid.", 
    "ModelState": { 
     "sendDate": [ 
      "Cannot convert value to DkDateTime" 
     ] 
    } 
} 
+0

其实,如果我在URI上给出一个错误的指导,我得到一个返回的web错误,就像一个坏的整数一样。我正在寻找让我的自定义对象导致相同的错误。如果ModelBinder是这样做的,我会研究这一点。 – galmok

+0

我实现了链接提供的ModelBinder示例,起初它不起作用。但是当我用throw FormatException替换了最后一个“返回false”时,我确实返回了一个web错误。谢谢。 :) – galmok

+0

很高兴能够帮到 – cleftheris