ASP.NET MVC 4自定义动作过滤器,包含动态数据

时间:2014-01-12 17:50:12

标签: asp.net asp.net-mvc asp.net-mvc-4 action-filter custom-action-filter

所以我正在构建一个我希望在完成它之后销售的Web应用程序。它允许用户在管理面板中输入数据,例如他们的网站名称,元关键字,联系电子邮件,电话,地址等。我写了一个动作过滤器,以便在我放置过滤器的每个请求中包含这些值,因此我不必每次都查询它们,因为这些值包含在整个站点的公共页脚中。但是,我了解到如果我使用这些值的新信息或不同信息更新数据库,它不会在网页上更新,我猜测是因为在应用程序启动时配置了动作过滤器。在Action Filter中,我使用存储库模式来查询这些值。我已经在下面包含了动作过滤器的代码。我如何才能获得Action Filter的便利,但是当数据库中的数据发生变化时,它能够动态更新它吗?谢谢!

public class ViewBagActionFilter : ActionFilterAttribute,IActionFilter
{
    Repositories.SettingsRepository _repo = new Repositories.SettingsRepository();

    void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);
    }

    void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
    {
        string siteName = _repo.GetSiteName();
        string siteDesc = _repo.GetSiteDescription();
        string siteKeywords = _repo.GetSiteKeywords();
        string googleAnalytics = _repo.GetGoogleAnalytics();
        string streetAddress = _repo.GetStreetAddress();
        string zipCode = _repo.GetZipCode();
        string city = _repo.GetCity();
        string state = _repo.GetState();
        string aboutUs = _repo.GetAboutUs();
        string phone = _repo.GetPhoneNumber();
        string contactEmail = _repo.GetContactEmail();

        if (!string.IsNullOrWhiteSpace(siteName) && siteName.Length > 0)
        {
            string[] splitSiteName = new string[siteName.Length/2];
            splitSiteName = siteName.Split(' ');
            if (splitSiteName.Length > 1)
            {
                filterContext.Controller.ViewBag.SiteName1 = splitSiteName[0];
                filterContext.Controller.ViewBag.SiteName2 = splitSiteName[1];
            }
            else
            {
                filterContext.Controller.ViewBag.SiteName1 = splitSiteName[0];
                filterContext.Controller.ViewBag.SiteName2 = "";
            }
        }
        //Set default values for common viewbag items that are on every page using ternary syntax
        filterContext.Controller.ViewBag.SiteDescription = (!string.IsNullOrWhiteSpace(siteDesc) && siteDesc.Length > 0) ? siteDesc : "";
        filterContext.Controller.ViewBag.SiteKeywords = (!string.IsNullOrWhiteSpace(siteKeywords) && siteKeywords.Length > 0) ? siteKeywords : "";
        filterContext.Controller.ViewBag.GoogleAnalytics = (!string.IsNullOrWhiteSpace(googleAnalytics) && googleAnalytics.Length > 0) ? googleAnalytics : "";
        filterContext.Controller.ViewBag.StreetAddress = (!string.IsNullOrWhiteSpace(streetAddress) && streetAddress.Length > 0) ? streetAddress : "";
        filterContext.Controller.ViewBag.ZipCode = (!string.IsNullOrWhiteSpace(zipCode) && zipCode.Length > 0) ? zipCode : "";
        filterContext.Controller.ViewBag.City = (!string.IsNullOrWhiteSpace(city) && city.Length > 0) ? city : "";
        filterContext.Controller.ViewBag.State = (!string.IsNullOrWhiteSpace(state) && state.Length > 0) ? state : "";
        filterContext.Controller.ViewBag.AboutUs = (!string.IsNullOrWhiteSpace(aboutUs) && aboutUs.Length > 0) ? aboutUs : "";
        filterContext.Controller.ViewBag.PhoneNumber = (!string.IsNullOrWhiteSpace(phone) && phone.Length > 0) ? phone : "";
        filterContext.Controller.ViewBag.ContactEmail = (!string.IsNullOrWhiteSpace(contactEmail) && contactEmail.Length > 0) ? contactEmail : "";
        base.OnActionExecuting(filterContext);   
    }
}

1 个答案:

答案 0 :(得分:1)

我将尝试解释动作过滤器的工作原理。

因此,如果扩展Action过滤器,则可以覆盖4种基本方法:

  • OnActionExecuting - 在执行控制器操作之前调用此方法。
  • OnActionExecuted - 执行控制器操作后调用此方法。
  • OnResultExecuting - 在执行控制器操作结果之前调用此方法。
  • OnResultExecuted - 执行控制器操作结果后调用此方法。

所以这意味着每次在Controller运行之前都会调用方法。

现在关于优化。

string siteName = _repo.GetSiteName();
        string siteDesc = _repo.GetSiteDescription();
        string siteKeywords = _repo.GetSiteKeywords();
        string googleAnalytics = _repo.GetGoogleAnalytics();
        string streetAddress = _repo.GetStreetAddress();
        string zipCode = _repo.GetZipCode();
        string city = _repo.GetCity();
        string state = _repo.GetState();
        string aboutUs = _repo.GetAboutUs();
        string phone = _repo.GetPhoneNumber();
        string contactEmail = _repo.GetContactEmail();

我建议你创建一个类

public class Site{
 public string SiteName{get;set;}
public string City{get;set;}
//And so on just to add all properties
}

然后在存储库中添加一个方法

_repo.GetSite(); //Which will return object Site

然后

filterContext.Controller.ViewBag.CurrentSite = _repo.GetSite(); 

现在可能对你来说最重要。为什么它不能按你的意愿工作,而且有点简单。属性类在应用程序启动时仅初始化一次,之后它不会重新加载,并且您的实现有点奇怪,因为

 Repositories.SettingsRepository _repo = new Repositories.SettingsRepository();

我想你在这里加载设置。因此,在您加载后,您不再重新加载...这意味着每次重新加载页面时都会得到相同的结果,但如果重新启动iis,则会刷新数据。 可能的解决方案

将_repo的初始化移动到OnActionExecuting,然后每次都会重新加载数据,或按照我的建议重写存储库

filterContext.Controller.ViewBag.CurrentSite = _repo.GetSite(); 

应始终从db。

加载新数据

希望有所帮助:)