簡體   English   中英

Web Api 2:自定義參數驗證(typeconverter)

[英]Web Api 2: Custom parameter validation (typeconverter)

在Web Api 2中,控制器上的方法可以具有多個從URI提供的參數,例如,將字符串轉換為int,如果無法將字符串轉換為int,則返回自動Web錯誤消息。

我想對自定義類型做同樣的事情。 我創建了一個僅包含DateTime對象的類,並且想要將Web URI字符串參數自定義轉換為該DateTime對象。 為此,我實現了TypeConverter。 有用。 我的問題是,如果給它一個錯誤的日期字符串,則不會出現任何Web錯誤,並且我的方法將得到一個空指針。 這是我的帶有類型轉換器的模型:

[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引起異常,則這將由Web api反映出來,並且會將Web錯誤消息發送回調用方。 如果我給“ 2a”作為狀態碼,則會收到如下所示的網絡錯誤:

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

如何使用typeconverter觸發相同的錯誤消息? 也許類型轉換器不能幫助您,但是我應該怎么看?

您正在執行的操作是正確的,這是設計使然。 想一想您對messageid參數中的無效Guid會有什么期望。 同樣的事情在那里發生。 路由不匹配,或者您收到的請求無效。 為了更好地控制模型狀態驗證和錯誤消息,您應該繼承IModelBinder並構建自定義DkDateTimeModelBinder

檢查這篇文章: 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我在下面得到了預期的http://localhost:4814/example/test?senddate=dsfasdafsd

狀態400錯誤的請求

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM