救命!我在MVC母版页中获得了存储库访问权限!重构时间!

时间:2011-02-11 23:04:38

标签: asp.net-mvc

我在 母版页 中有以下代码来加载一些自定义内容,例如css文件,页脚中的一些地址信息,页眉/页脚logo等。我面临的加载时间长达一分钟!这是 可怕的 练习,我知道 - 我只是将其破解以使其正常运行。加载此类自定义信息的最佳做法是什么?

目前,我尝试加载一个cookie - 检查它是否具有所需的密钥,如果它没有 - 从数据库加载信息。我希望有一些类似于.config文件,如果可能的话,它会缓存在客户端机器上。

所有信息都存储在名为StoreSettings的表中,该表通过StoreSettingsID链接到Reseller表。

<head id="Head1">
    <%

        HttpCookie storeSettingsCookie = Request.Cookies["StoreSettings"];
        try
        {
            if (storeSettingsCookie == null || storeSettingsCookie.HasKeys == false)
            {
                if (Context.User.Identity.IsAuthenticated && Context.User.IsInRole("Reseller"))
                {
                    var reseller = new Reseller();
                    var storeSettings = new StoreSettings();

                    var resellerRepository = new ResellerRepository();
                    reseller = resellerRepository.GetResellerByUsername(Context.User.Identity.Name);

                    if (reseller.StoreSettingsID != null && reseller.StoreSetting.Theme != null)
                    {
                        var storeSettingsRepository = new StoreSettingsRepository();
                        storeSettings = storeSettingsRepository.GetStoreSettings((int)reseller.StoreSettingsID);

                        storeSettingsCookie = new HttpCookie("StoreSettings");

                        storeSettingsCookie["HeaderImage"] = storeSettings.Image1.FileName;
                        storeSettingsCookie["FooterImage"] = storeSettings.Image.FileName;
                        storeSettingsCookie["ThemeLocation"] = storeSettings.Theme.StylesheetLocation;
                        storeSettingsCookie["StoreName"] = storeSettings.StoreName;
                        storeSettingsCookie["Address1"] = storeSettings.Address1;
                        storeSettingsCookie["Address2"] = storeSettings.Address2;
                        storeSettingsCookie["City"] = storeSettings.City;
                        storeSettingsCookie["PostalCode"] = storeSettings.PostalCode;
                        storeSettingsCookie["ProvinceCode"] = storeSettings.Province.Abbreviation;
                        storeSettingsCookie["Phone"] = storeSettings.Phone;

                        Response.Cookies.Add(storeSettingsCookie);
                    }
                    else
                    {
                        storeSettingsCookie = new HttpCookie("StoreSettings");

                        storeSettingsCookie["ThemeLocation"] = "~/Content/jquery-ui-1.8.9.custom.css";
                        storeSettingsCookie["StoreName"] = "";
                        storeSettingsCookie["Address1"] = "";
                        Response.Cookies.Add(storeSettingsCookie);
                    }
                }
            }
        }
        catch
        {

        }


    %>
    <title>
        <asp:ContentPlaceHolder ID="TitleContent" runat="server" />
        |
        <%: string.IsNullOrEmpty(storeSettingsCookie["StoreName"]) ? "My Store Name" : storeSettingsCookie["StoreName"] %>
    </title>

... <%-- Css/JS --%>

</head>

任何建议都表示赞赏。我期待来自MVC人员的很多叹息。我知道这不是MVC的工作方式,所以请不要提醒我,哈哈。 :)

修改

好的,所以按照LukLed的建议,我已经创建了一个基本控制器类,将上面的代码粘贴在它的构造函数中并让我的控制器继承它。这似乎可以工作,但User对象为null。我应该如何解决这个问题?这就是我所拥有的:

  public BaseController()
        {
            var resellerRepository = new ResellerRepository();
            var reseller = resellerRepository.GetResellerByUsername(User.Identity.Name);

            if (reseller.StoreSettingsID != null && reseller.StoreSetting.Theme != null)
            {
                var storeSettingsRepository = new StoreSettingsRepository();
                var storeSettings = storeSettingsRepository.GetStoreSettings((int)reseller.StoreSettingsID);

                ViewData["HeaderImage"] = storeSettings.Image1.FileName;
                ViewData["FooterImage"] = storeSettings.Image.FileName;
                ViewData["ThemeLocation"] = storeSettings.Theme.StylesheetLocation;
                ViewData["StoreName"] = storeSettings.StoreName;
                ViewData["Address1"] = storeSettings.Address1;
                ViewData["Address2"] = storeSettings.Address2;
                ViewData["City"] = storeSettings.City;
                ViewData["PostalCode"] = storeSettings.PostalCode;
                ViewData["ProvinceCode"] = storeSettings.Province.Abbreviation;
                ViewData["Phone"] = storeSettings.Phone;
            }
            else
            {
                ViewData["ThemeLocation"] = "~/Content/jquery-ui-1.8.9.custom.css";
                ViewData["StoreName"] = "";
                ViewData["Address1"] = "";
            }
        }

经销商必须登录才能查看商店。

修改

所以这是我在遵循Darins建议后所处的位置 - 我升级到MVC3并使用了一个GlobalActionFilter,它在调用每个动作后执行。我如何防止这种情况 - 因为它执行4-5次。此外 - 每次viewdata都为null。我做错了什么?

这是我的动作过滤器(我没有使用Darin的示例中的Automapper,因为StoreSettings没有直接转换为StoreSettingsViewModel,我希望看到这个工作,首先)

 public class StoreSettingsActionFilter : ActionFilterAttribute
    {
        private readonly IResellerRepository _resellerRepository;
        private readonly IStoreSettingsRepository _storeSettingsRepository;

        public StoreSettingsActionFilter(
            IResellerRepository resellerRepository,
            IStoreSettingsRepository storeSettingsRepository
        )
        {
            _resellerRepository = resellerRepository;
            _storeSettingsRepository = storeSettingsRepository;
        }

        public StoreSettingsActionFilter()
            : this(new ResellerRepository(), new StoreSettingsRepository())
        {

        }

        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            base.OnResultExecuted(filterContext);

            var settingsViewModel = new StoreSettingsViewModel();
            settingsViewModel.ThemeLocation = "~/Content/jquery-ui-1.8.9.custom.css";
            var user = filterContext.HttpContext.User;
            if (!user.Identity.IsAuthenticated || !user.IsInRole("Reseller"))
            {
                filterContext.Controller.ViewData["storeSettings"] = settingsViewModel;
                return;
            }

            var session = filterContext.HttpContext.Session;
            var reseller = session["reseller"] as Reseller;
            if (reseller == null)
            {
                reseller = _resellerRepository.GetResellerByUsername(user.Identity.Name);
                session["reseller"] = reseller;
            }

            if (reseller.StoreSettingsID != null && reseller.StoreSetting.Theme != null)
            {
                var storeSettings = session["storeSettings"] as StoreSettings;
                if (storeSettings == null)
                {
                    storeSettings = _storeSettingsRepository.GetStoreSettings((int)reseller.StoreSettingsID);
                    session["storeSettings"] = storeSettings;
                }
                // Using AutoMapper to convert between the model and the view model
                //settingsViewModel = Mapper.Map<StoreSettings, StoreSettingsViewModel>(storeSettings);

                settingsViewModel.ThemeLocation = storeSettings.Theme.StylesheetLocation;
                settingsViewModel.Address1 = storeSettings.Address1;
                settingsViewModel.Address2 = storeSettings.Address2;
                settingsViewModel.City = storeSettings.City;
                settingsViewModel.FooterImage = storeSettings.Image.FileName;
                settingsViewModel.HeaderImage = storeSettings.Image1.FileName;
                settingsViewModel.Phone = storeSettings.Phone;
                settingsViewModel.PostalCode = storeSettings.PostalCode;
                settingsViewModel.ProvinceCode = storeSettings.Province.Abbreviation;
                settingsViewModel.StoreName = storeSettings.StoreName;
            }
            filterContext.Controller.ViewData["storeSettings"] = settingsViewModel;
        }
    }

这是我注册全局动作过滤器的地方

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    //Register the global action filter
    GlobalFilters.Filters.Add(new StoreSettingsActionFilter());

    //RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
}

1 个答案:

答案 0 :(得分:2)

我会使用一个动作过滤器,它会在每个请求上注入商店设置。视图模型可能如下所示:

public class StoreSettingsViewModel
{
    public string HeaderImage { get; set; }
    public string FooterImage { get; set; }
    public string ThemeLocation { get; set; }
    public string StoreName { get; set; }
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string PostalCode { get; set; }
    public string ProvinceCode { get; set; }
    public string Phone { get; set; }
}

动作过滤器:

public class StoreSettingsActionFilter : ActionFilterAttribute
{
    private readonly IResellerRepository _resellerRepository;
    private readonly IStoreSettingsRepository _storeSettingsRepository;

    public StoreSettingsActionFilter(
        IResellerRepository resellerRepository,
        IStoreSettingsRepository storeSettingsRepository
    )
    {
        _resellerRepository = resellerRepository;
        _storeSettingsRepository = storeSettingsRepository;
    }

    public StoreSettingsActionFilter() 
        : this(new ResellerRepository(), new StoreSettingsRepository())
    { }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        base.OnResultExecuted(filterContext);

        var settingsViewModel = new StoreSettingsViewModel();
        settingsViewModel.ThemeLocation = "~/Content/jquery-ui-1.8.9.custom.css";
        var user = filterContext.HttpContext.User;
        if (!user.Identity.IsAuthenticated || !user.IsInRole("Reseller"))
        {
            filterContext.Controller.ViewData["storeSettings"] = settingsViewModel;
            return;
        }

        var session = filterContext.HttpContext;
        var reseller = session["reseller"] as Reseller;
        if (reseller == null)
        {
            reseller = _resellerRepository.GetResellerByUsername(user.Identity.Name);
            session["reseller"] = reseller;
        }

        if (reseller.StoreSettingsID != null && reseller.StoreSetting.Theme != null)
        {
            var storeSettings = session["storeSettings"] as StoreSettings;
            if (storeSettings == null)
            {
                storeSettings = _storeSettingsRepository.GetStoreSettings((int)reseller.StoreSettingsID);
                session["storeSettings"] = storeSettings;
            }
            // Using AutoMapper to convert between the model and the view model
            settingsViewModel = Mapper.Map<StoreSettings, StoreSettingsViewModel>(storeSettings);
        }
        filterContext.Controller.ViewData["storeSettings"] = settingsViewModel;
    }
}

现在我们需要在基本控制器上应用此属性,以便为每个操作执行它:

[StoreSettings]
public abstract class BaseController : Controller
{
}

如果您使用的是ASP.NET MVC 3,则可以使用global action filter

最后,在母版页中,您可以访问商店设置:

<% 
    var storeSettings = (StoreSettingsViewModel)ViewData["storeSettings"];
%>

<title>
    <asp:ContentPlaceHolder ID="TitleContent" runat="server" />
    <%: storeSettings.StoreName ?? "My Store Name" %>
</title>
<%-- Css/JS --%>
...