ASP.NET MVC中用于GET请求的自定义模型绑定器

21

我创建了一个自定义的MVC模型绑定器,每当服务器接收到HttpPost请求时就会调用它。但是对于HttpGet请求不会调用。

  • 我的自定义模型绑定器是否应该在GET期间被调用?如果是,那么我错过了什么?
  • 如果不应该,在GET请求中如何编写处理QueryString的自定义代码?

以下是我的实现...

public class CustomModelBinder : DefaultModelBinder
{
   public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
   {
      // This only gets called for POST requests. But I need this code for GET requests.
   }
}

全局.asax

protected void Application_Start()
{
   ModelBinders.Binders.DefaultBinder = new CustomModelBinder();
   //...
}

我研究过这些解决方案,但它们并不完全适用于我所需要的内容:

  • 通过TempData持久化复杂类型
  • 使用默认绑定器构建复杂类型(?Name=John&Surname=Doe

回答备注

感谢@Felipe的帮助。以防有人遇到同样的问题,我学到了:

  • 自定义模型绑定器可以用于GET请求
  • 可以使用DefaultModelBinder
  • 我的问题在于操作方法必须具有参数(否则模型绑定器会跳过GET请求,如果你想一下就会明白为什么)

你可以使用OnActionExecuting来过滤每个请求,在该方法中,你可以使用Request获取查询字符串。 - J Santosh
@JSantosh,假设我在OnActionExecuting中获取到了我的QueryString。那么我就不能将QueryString转换为对象并将其作为参数传递给操作方法了,是吧?这让我陷入了同样的困境。 - Niels Filter
在POST请求中,您会将数据作为对象获取,该对象会自动解析为相应的模型,但在GET请求中,您获取到的数据是字符串,我不确定您是否可以实现这一点。好问题 :) - J Santosh
谢谢 @JSantosh :) 我有的代码可以将 QueryString 从字符串转换为我的自定义对象,这很好。现在只是把那个构建出来的对象传递给 Action 参数的问题... - Niels Filter
1个回答

21

假设你有自己想要绑定的数据类型。

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    // other properties you need
}

您可以为此特定类型创建一个自定义模型绑定器,继承自DefaultModelBinder,例如:

public class PersonModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var request = controllerContext.HttpContext.Request;

        int id = Convert.ToInt32(request.QueryString["id"]);
        string name = request.QueryString["name"];
        int age = Convert.ToInt32(request.QueryString["age"]);
        // other properties

        return new Person { Id = id, Name = name, Age = age };
    }
}

在Global.asax文件的Application_Start事件中,您可以注册此模型绑定,例如:

// for Person type, bind with the PersonModelBinder
ModelBinders.Binders.Add(typeof(Person), new PersonModelBinder());

PersonModelBinderBindModel方法中,请确保您已经获取了查询字符串中所有的参数,并对它们进行合适的处理。

因为您有这个动作方法:

public ActionResult Test(Person person)
{
  // process...
}

您可以通过类似以下的网址访问此操作:

Test?id=7&name=Niels&age=25

感谢详细的回答。我正在使用DefaultModelBinder(请参考我的问题),在GET请求中似乎没有被触发,只有在POST请求中才会。您的BindModel方法是否也会在HttpGet请求中被调用? - Niels Filter
我已经在这里进行了测试,在“Test”操作方法中,我已经成功填充了“person”参数。确保您已经为自定义类型注册了自定义绑定。请记住,您还需要从“request.QueryString”中读取。 - Felipe Oriani
太棒了,那我在我的一面漏掉了什么。让我试试然后再回复你。谢谢。 - Niels Filter
谢谢Felipe,现在它可以工作了。原来如果您对“Action”方法执行“Get”请求而没有任何参数,则不会通过模型绑定器(我猜为什么需要)进行操作。 - Niels Filter
1
@Niels Filter,感谢您的观点“事实证明,如果您对Action方法执行Get请求而没有任何参数,则不会通过模型绑定器”。即使它是一个虚拟参数,该参数似乎仍然需要触发MVC模型绑定。 - Thomas.Benz
在我的项目中,IModelBinderDafaultModelBinderSystem.Web.Http.ModelBindingSystem.Web.MvcSystem.Web.ModelBinging 之间存在歧义,哪一个是适用于 ASP.NET MVC 的正确选项? - Hamed Zakery Miab

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接