基於通用會話的模型繫結

有時我們需要保留整個模型並將其轉移到操作甚至控制器之間。針對此類要求在會話良好解決方案中儲存模型。如果我們將它與 MVC 強大的模型繫結功能結合起來,我們就會得到優雅的方式。我們可以通過三個簡單步驟建立基於通用會話的模型繫結:

第一步:建立模型繫結器

建立一個模型繫結器本身。我個人在 / Infrastructure / ModelBinders 資料夾中建立了 SessionDataModelBinder 類。 **

using System;
using System.Web.Mvc;

public class SessionDataModelBinder<TModel>
    : IModelBinder
    where TModel : class
{
    private string SessionKey { get; set; }

    public SessionDataModelBinder(string sessionKey)
    {
        if (string.IsNullOrEmpty(sessionKey))
            throw new ArgumentNullException(nameof(sessionKey));
        SessionKey = sessionKey;
    }

    public object BindModel(
        ControllerContext controllerContext, 
        ModelBindingContext bindingContext)
    {
        // Get model from session
        TModel model = controllerContext
            .HttpContext
            .Session[SessionKey] as TModel;
        // Create model if it wasn't found from session and store it
        if (model == null)
        {
            model = Activator.CreateInstance<TModel>();
            controllerContext.HttpContext.Session[SessionKey] = model;
        }
        // Return the model
        return model;
    }
}

第二步:註冊活頁夾

如果我們有如下模型:

public class ReportInfo
{
    public int ReportId { get; set; }
    public ReportTypes TypeId { get; set; }
}

public enum ReportTypes
{
    NotSpecified,
    Monthly, Yearly
}

我們可以在 Application_Start 方法中的 Global.asax 中為此模型註冊基於會話的模型繫結器 : **

protected void Application_Start()
{
    .........

    // Model binders.
    // Remember to specy unique SessionKey
    ModelBinders.Binders.Add(typeof(ReportInfo), 
        new SessionDataModelBinder<ReportInfo>("ReportInfo"));
}

第三步:使用它!

現在,我們只需在操作中新增引數即可從此模型繫結器中受益 :

public class HomeController : Controller
{
    public ActionResult Index(ReportInfo reportInfo)
    {
        // Simply set properties
        reportInfo.TypeId = ReportTypes.Monthly;

        return View();
    }

    public ActionResult About(ReportInfo reportInfo)
    {
        // reportInfo.TypeId is Monthly now because we set
        // it previously in Index action.
        ReportTypes currentReportType = reportInfo.TypeId;

        return View();
    }
}