基于ASP.NET MVC会话的模型绑定器 - 更新值返回会话

时间:2013-07-12 15:48:33

标签: asp.net-mvc model-binding

根据Steve Sanderson在book中的样本,他提供了如何使用session实现自定义模型绑定器的示例。当然它需要在global.asax.cs中注册。

public class CartModelBinder : IModelBinder
{
    private string sessionKey = "Cart";

    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        Cart cart = (Cart)controllerContext.HttpContext.Session[this.sessionKey];
        if (cart == null)
        {
            cart = new Cart();
            controllerContext.HttpContext.Session[this.sessionKey] = cart;
        }

        return cart;
    }
}

模式类

public class Cart
{
    private List<int> itemList;

    public List<int> ItemList
    {
        get
        {
            return this.itemList;
        }
    }

    public Cart()
    {
        this.itemList = new List<int>();
    }

    public void AddItem(int itemId)
    {
        this.itemList.Add(itemId);
    }
}

然后在控制器/动作中使用它:

public class HomeController : Controller
{
    public ActionResult Index(Cart cart)
    {
        return View();
    }

    [HttpPost]
    public ActionResult AddToCart(Cart cart, int id)
    {
        cart.AddItem(id);

        return View(cart);
    }
}

Index.cshtml查看

@model MvcApplication2.Models.Cart

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    <div>
        @using (@Html.BeginForm("AddToCart", "Home")) {
        <h1>Cart form</h1>
            @Html.TextBox("id")

            <input type="submit" />
        }
    </div>
</body>
</html>

AddToCart.cshtml查看

@model MvcApplication2.Models.Cart

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>AddToCart</title>
</head>
<body>
    <div>
        @foreach (int itemId in Model.ItemList)
        { 
            @Html.Label(itemId.ToString())<br />
        }
        @Html.ActionLink("Go back", "Index")
    </div>
</body>
</html>

但我的问题是,我没有看到任何代码将值更新回会话。它是如何发生的?

1 个答案:

答案 0 :(得分:0)

您需要将其保存回控制器中的Session:

public RedirectToRouteAction AddToCart(Cart cart)
{
    cart.AddItem(newItem);

    HttpContext.Session["Cart"] = cart;
}

更新: 会话变量存储在实现IEnumerable和ICollection的SessionStateItemCollection对象中。在Session中保存对象时,只存储对象的引用,而不是它的新实例。因此,当您对对象进行更改时,实际上是对Session中的同一对象进行了更改(对它的引用存储在Session中)。这就像创建一个对象并将其添加到List一样。在将对象添加到List后更新对象时,实际上是在List中更新相同的实例。

因此,在这种情况下,您不必将购物车保存回会话,因为模型活页夹只有在会话中没有购物车时才会创建新购物车,所以只要会话处于活动状态,只有一个Cart对象。