处理在控制器操作中解析可为空的参数导致的异常

时间:2019-05-29 04:15:28

标签: c# asp.net-mvc

我有一个终点

[HttpGet]
public async Task<ActionResult> GetNodes([FromQuery] Guid? parentId)

然后这样称呼它 GET .../api/nodes?parentId=null
解析参数"The value 'null' is not valid."时Asp.net引发异常 如果发生异常,如何重写该行为以使其将可为空的类型解析为null?

我希望:
GET .../api/nodes?parentId=null应该用parentId == null

调用操作

GET .../api/nodes?parentId=50d21ddd-6a95-46db-bff9-c943cf5b0df1应该用parentId = "50d21ddd-6a95-46db-bff9-c943cf5b0df1"来调用操作


GET .../api/nodes?parentId=something_not_parsable_to_guid应该用parentId = null来调用操作

3 个答案:

答案 0 :(得分:1)

@Karan的解决方案是您应该使用的方法。但是,如果您不愿意更改客户端脚本,则仍然可以选择如下:

[HttpGet]
public async Task<ActionResult> GetNodes() {
     var parentId = Request.QueryString["parentId"].ToString();
     Guid guid;
     if (Guid.TryParse(parentId , out guid))
     {
       // use guid here
     }

}

答案 1 :(得分:1)

将您的Guid参数转换为string,然后尝试使用Guid.TryParse

[HttpGet]
public async Task<ActionResult> GetNodes([FromQuery] string parentId)
{
        Guid guid;
        if (Guid.TryParse(parentId, out guid))
        {
            // code when guid is not null.
            // use guid object.
        }
        else
        {
            // code when guid is null.
        }
}

答案 2 :(得分:0)

我刚刚做了一个简单的IModelBinder,如果它支持默认转换,它将把字符串转换成所需类型的实例
代码看起来像这样:

public Task BindModelAsync(ModelBindingContext bindingContext)
{
    var targetType = bindingContext.ModelType;
    var targetName = bindingContext.ModelName;
    var stringValue = bindingContext.ValueProvider.GetValue(targetName).FirstValue;

    var isNullableOrReference = Nullable.GetUnderlyingType(targetType) != null ||
                                !targetType.IsValueType;

    var valueProvider = bindingContext.ValueProvider.GetValue(targetName);
    try
    {
        var converter = TypeDescriptor.GetConverter(targetType);
        var resultValue = converter.ConvertFromString(stringValue);

        bindingContext.Result = ModelBindingResult.Success(resultValue);
        bindingContext.ModelState.SetModelValue(targetName, valueProvider);
    }
    catch (NotSupportedException e)
    {
        bindingContext.Result = ModelBindingResult.Failed();
        return Task.CompletedTask;
    }
    catch (Exception e)
    {
        bindingContext.Result = ModelBindingResult.Success(isNullableOrReference ? null : Activator.CreateInstance(targetType));
        bindingContext.ModelState.SetModelValue(targetName, valueProvider);
    }

    return Task.CompletedTask;
}

它需要进行一些调整,但是它可以按我希望的那样工作