ASP.NET MVC:在模型绑定中强制转换的类型

时间:2014-10-31 11:41:09

标签: c# asp.net-mvc casting asp.net-mvc-5 model-binding

有没有办法在ASP.NET MVC 5中将控制器操作中的参数从一种类型转换为另一种类型?

实施例。行动方法如下:

public string Test(Guid input) {
    return "";
}

如果使用参数调用方法" input = hello"然后我收到错误消息:"参数字典包含参数'输入'的空条目。非可空类型的System.Guid'方法' System.String测试(System.Guid)'在RealtyGuide.WebSite.Controllers.HomeController'中。可选参数必须是引用类型,可以为空的类型,或者声明为可选参数。"

我想要的是尝试根据特定(自定义)规则将参数强制转换为Guid。这是关于模型绑定的问题吗?有哪些方法可以解决这个问题?抱歉我的英文。

关于答案。如果您只想为Guid参数指定null,如果它无效,请查看this answer。如果您正在寻找自定义模型绑定器的示例,请查看thisthis个答案。

4 个答案:

答案 0 :(得分:2)

根据@AndreiV和@AntP的评论,决定是:

  1. 如果字符串是正确的Guid字符串,那么它会自动绑定(不需要任何其他内容),

  2. 如果字符串不是正确的Guid字符串,那么

  3. 2.1。在动作的主体中进行转换(在我看来,它需要代码重复)或

    2.2。设置自定义(用户定义)模型绑定器。以下是最后一种方法的代码(模型绑定器)。

    // This is an example. 
    // Note the returning of null which is undesired.
    // Also it does not deal with exceptions handling. Use it only as a stub.
        public class ExtendedModelBinder : DefaultModelBinder {
                public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
                    if (!(bindingContext.ModelType == typeof(Guid)))
                        return base.BindModel(controllerContext, bindingContext);
                    if (!bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName))
                        return null;
                    string input = bindingContext.ValueProvider.GetValue(bindingContext.ModelName).AttemptedValue;
                    if (string.IsNullOrEmpty(input))
                        return null;
                    Guid g;
                    if (Guid.TryParse(input, out g))
                        return g;
                    var bytes = HttpServerUtility.UrlTokenDecode(s);
                    var result = new Guid(bytes);
                    return result;
                }
            }
    

    必须在Application_Start中注册:

    ModelBinders.Binders.Add(typeof(Guid), new RealtyGuide.WebSite.Extensions.MyModelBinder());
    

    可以使用属性而不是全局注册绑定器(请参阅here),但我不会使用它,因为它在我的任务中需要不必要的代码重复。

    参考:123

答案 1 :(得分:2)

回复Hoborg的例子,https://stackoverflow.com/posts/26676337/revisions 如果需要,以下内容将返回空值或Guid参数。

public class NullableGuidBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType == typeof(Guid?))
        {
            var valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

            string input = valueResult.AttemptedValue;
            if (string.IsNullOrEmpty(input) || input == "0")
            {
                // return null, even if input = 0
                // however, that is dropdowns' "guid.empty")
                // base.BindModel(...) would fail converting string to guid, 
                // Guid.Parse and Guid.TryParse would fail since they expect 000-... format

                // add the property to modelstate dictionary
                var modelState = new ModelState { Value = valueResult };
                bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
                return null;
            }
        }

        return base.BindModel(controllerContext, bindingContext);
    }
}

在控制器中进行如下绑定

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> SelectAction(
        [ModelBinder(typeof(NullableGuidBinder))] Guid? id)
    {
        // your stuff
    }

答案 2 :(得分:1)

当在值无效时搜索Guid绑定操作与优雅后备时,我偶然发现了这个问题。如果不必知道实际提供的值,那么使用nullable GuidGuid?)就可以了。例如。 (这是在ASP.NET Web API中测试的):

[Route("Test")]
[HttpGet]
public string Test(Guid? input = null)

如果提供了有效的Guid,则会填充输入。否则,它将是null

答案 3 :(得分:0)

尝试输入=&#34; helo&#34;是一种错误的方法。 Guid必须包含32位数值示例(12345678910111213141516171819202)

尝试此输入= 12345678910111213141516171819202, 通过给出32位数字的值,Guid值接受它。 然后该方法将不会显示相同的错误。

var input = 12345678910111213141516171819202;

public string Test(Guid input) {
return "";
}