Фильтры настраиваемых действий ASP.NET MVC 4 с динамическими данными

Итак, я создаю веб-приложение, которое хочу продать, как только закончу с ним. Это позволяет пользователю вводить такие данные, как название своего веб-сайта, мета-ключевые слова, контактный адрес электронной почты, телефон, адрес и т. д. в панели администратора. Я написал фильтр действий, чтобы включать эти значения в каждый запрос, на который я наложил фильтр, чтобы мне не приходилось запрашивать их каждый раз, потому что эти значения включены в общий нижний колонтитул по всему сайту. Однако я узнал, что если я обновляю базу данных новой или другой информацией для этих значений, она не обновляется на веб-страницах, что, как я предполагаю, связано с тем, что фильтры действий настраиваются при запуске приложения. В фильтре действий я использую шаблон репозитория для запроса этих значений. Я включил код для фильтра действий ниже. Как я могу использовать удобство фильтра действий, но при этом иметь возможность динамически обновлять его при изменении данных в базе данных? Спасибо!

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

person vol4life27    schedule 12.01.2014    source источник


Ответы (1)


Я попытаюсь объяснить, как работают фильтры действий.

Поэтому, если вы расширите фильтр действий, вы можете переопределить 4 базовых метода:

  • OnActionExecuting — этот метод вызывается перед выполнением действия контроллера.
  • OnActionExecuted — этот метод вызывается после выполнения действия контроллера.
  • OnResultExecuting — этот метод вызывается перед выполнением результата действия контроллера.
  • OnResultExecuted — этот метод вызывается после выполнения результата действия контроллера.

Это означает, что ваш метод будет вызываться каждый раз перед тем, как контроллер запустит действие.

Теперь об оптимизации. У тебя есть

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

Всегда должен загружать новые данные из БД.

Надеюсь, поможет :)

person Vova Bilyachat    schedule 13.01.2014