为存储在会话中的对象扩展Sanderson的自定义mvc ModelBinder

时间:2009-08-26 09:55:11

标签: asp.net-mvc modelbinders imodelbinder

在他精彩的MVC书中,Steven Sanderson给出了一个自定义模型绑定器的示例,它设置和检索会话变量,将数据存储元素隐藏在控制器中。

我正在尝试扩展它以满足一个非常常见的场景:我在会话中存储一个User对象,并将其作为参数提供给每个操作方法。当用户详细信息没有改变时,Sanderson的课程工作正常,但现在我需要让用户编辑他们的详细信息并将修改后的对象保存回会话。

我的问题是,除了通过检查bindingContext.ValueProvider.Keys中的键数,我无法弄清楚如何区分GET和POST,这看起来很错误我确定我误解了一些东西

有人能指出我正确的方向吗?基本上所有Actions都需要访问当前用户,UpdateMyDetails操作需要更新同一个对象,所有对象都由Session支持。这是我的代码......

public class CurrentUserModelBinder : IModelBinder
{
    private const string userSessionKey = "_currentuser";
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
        var user = controllerContext.HttpContext.Session[userSessionKey];
        if (user == null)
            throw new NullReferenceException("The CurrentUser was requested from the CurrentUserModelBinder but no IUser was present in the Session.");

        var currentUser = (CCL.IUser)user;
        if (bindingContext.ValueProvider.Keys.Count > 3)
        {

            var firstName = GetValue<string>(bindingContext, "FirstName");
            if (string.IsNullOrEmpty(firstName))
                bindingContext.ModelState.AddModelError("FirstName", "Please tell us your first name.");
            else
                currentUser.FirstName = firstName;

            var lastName = GetValue<string>(bindingContext, "LastName");
            if (string.IsNullOrEmpty(lastName))
                bindingContext.ModelState.AddModelError("LastName", "Please tell us your last name.");
            else
                currentUser.LastName = lastName;

            if (bindingContext.ModelState.IsValid)
                controllerContext.HttpContext.Session[userSessionKey] = currentUser;

        }
        return currentUser;
    }
    private T GetValue<T>(ModelBindingContext bindingContext, string key)
    {
        ValueProviderResult valueResult;
        bindingContext.ValueProvider.TryGetValue(key, out valueResult);
        bindingContext.ModelState.SetModelValue(key, valueResult);
        return (T)valueResult.ConvertTo(typeof(T));
    }  
}

1 个答案:

答案 0 :(得分:1)

尝试继承DefaultModelBinder而不是IModelBinder,然后你可以调用base.BindModel为mvc 1.0填充bindingContext.Model或为mvc 2.0填充bindingContext.ModelMetadata.Model

要触发bindingContext.Model填充,请在控制器上调用UpdateModel。

您需要在

中添加本书中的陈述
if(bindingContext.Model != null)
throw new InvalidOperationException("Cannot update instances");

但是将其更改为填充模型并保存在会话中。

if(bindingContext.Model != null)
{
    base.BindModel(controllerContext, bindingContext);
    //save bindingContext.Model to session, overwriting current.
    return bindingContext.Model
}