【问题标题】:ASP.NET MVC 4 Custom Action filters with dynamic data带有动态数据的 ASP.NET MVC 4 自定义操作过滤器
【发布时间】:2014-01-12 17:50:11
【问题描述】:

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

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

【问题讨论】:

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


    【解决方案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 加载新数据。

    希望对你有帮助:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-06
      • 2018-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多