为存储在会话中的对象扩展Sanderson的自定义mvc ModelBinder [英] Extending Sanderson's custom mvc ModelBinder for an object stored in session

查看:79
本文介绍了为存储在会话中的对象扩展Sanderson的自定义mvc ModelBinder的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

史蒂文·桑德森(Steven Sanderson)在其精彩的MVC书中给出了一个自定义模型绑定器的示例,该绑定器设置和检索会话变量,从而从控制器中隐藏数据存储元素.

In his wonderful MVC book Steven Sanderson gives an example of a custom model binder that sets and retrieves a session variable, hiding the data storage element from the controller.

我正在尝试扩展它,以适应一个非常常见的情况:我在会话中存储一个User对象,并将其作为参数提供给每个action方法.当用户详细信息未更改时,Sanderson的班级工作正常,但是现在我需要让用户编辑其详细信息,并将修改后的对象保存回会话.

I'm trying to extend this to cater for a pretty common scenario: I'm storing a User object in the session and making this available to every action method as a parameter. Sanderson's class worked ok when the User details weren't changing, but now i need to let the user edit their details and save the amended object back to the session.

我的问题是,除了检查bindingContext.ValueProvider.Keys中的键数之外,我无法确定如何将GET与POST区别开来,这似乎是错的,我敢肯定我误会了一些东西

My problem is that I can't work out how to distinguish a GET from a POST other than by checking the number of keys in bindingContext.ValueProvider.Keys, and this seems so wrong I'm sure I'm misunderstanding something.

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

Can anyone point me in the right direction? Basically all Actions need access to the current user, and the UpdateMyDetails action needs to update that same object, all backed by the Session. Here's my code...

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));
    }  
}

推荐答案

尝试从DefaultModelBinder而不是IModelBinder继承,则可以调用base.BindModel填充mvc 1.0的bindingContext.Model或mvc 2.0的bindingContext.ModelMetadata.Model

Try inheriting from DefaultModelBinder instead of IModelBinder, then you can call base.BindModel to populate bindingContext.Model for mvc 1.0 or bindingContext.ModelMetadata.Model for mvc 2.0

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

To trigger bindingContext.Model to populate, call UpdateModel on the controller.

您需要重新添加书中的声明

You need to add the statement from the book back in

if(bindingContext.Model != null)
throw new InvalidOperationException("Cannot update instances");

但将其更改以填充模型并保存在会话中.

but change it to populate model and save on the session.

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

这篇关于为存储在会话中的对象扩展Sanderson的自定义mvc ModelBinder的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆