2010-09-08 2 views
2

Предыстория:Возможно ли сделать данные из метода действий доступными в фильтре действий?

Мы поставляются с HTML файлами - «бандеролей» - от нашего клиента, в который мы должны придать содержание, которое мы производим. У них разные обертки для разных страниц, и мы должны вводить соответствующий контент в специальный тег, который они содержат в обертке.

Имя файла-обертки соответствует имени метода действия. Таким образом, для примера ниже выполняется пользовательский фильтр действий, который определит имя обертки, а затем вызовет метод в BaseController (который каждый контроллер реализует), который загрузит оболочку и введет наш контент в нее.

[WrapperAction] 
    public ActionResult Home() 
    { 
     return View(); 
    } 

Причина я положил это в ActionFilter, потому что я не хочу быть вызовом метода BaseController «s для заполнения оболочки в каждом методе действий, который нуждался в обертке. Я думал, что это было гораздо опрятнее украсить метод с ActionFilterAttribute

WrapperAction определяется следующим образом:

public class WrapperAction : ActionFilterAttribute 
{ 
    public override void OnActionExecuted(ActionExecutedContext aec) 
    { 
     var baseController = (BaseController)filterContext.Controller; 

     string wrapper = aec.RequestContext.RouteData.Values["action"].ToString(); 

     baseController.PopulateWrapper(wrapper); 
    } 
} 

и PopulateWrapper определяется как

public void PopulateWrapper(string wrapperName) 
    { 
     // get wrapper file from disk 
     Wrapper wrapper = _wrapperService.GetWrapper(Site.Id, wrapperName); 

     // populate the file with our CSS (it already has its own pre-populated CSS) 
     // our CSS file is determined by the id of a Site object. 
     AppHelper.PopulateWrapperCss(wrapper, this.Site.Id); 

     // make wrapper sections available to the Master page, 
     // split so that we can place our content around them 
     ViewData["WrapperTop"] = wrapper.WrapperTop; 
     ViewData["WrapperMiddle"] = wrapper.WrapperMiddle; 
     ViewData["WrapperBottom"] = wrapper.WrapperBottom; 
    } 

The Дилема:

Теперь, однако, появилось новое требование. Есть несколько новых тегов в wr apper, который мне нужно заполнить, и я должен заполнить их разными данными в зависимости от метода действия, который вызывает оболочку. Эти данные определяются в методах действий, но данные должны использоваться в методе PopulateWrapper, который вызывается WrapperAction.

мне теперь нужно иметь метод, аналогичный

AppHelper.PopulateWrapperTags(wrapper, this.TagData);

и мне нужно иметь какой-то способ для недвижимости TagData BaseController для заполняться данными. Я могу Asign свойство в способе действия, как следует

[WrapperAction] 
    public ActionResult Home() 
    { 
     base.TagData = GetTagData(); 
     return View(); 
    } 

но такого рода поражений точки меня, имеющей WrapperAction в первую очередь потому, что я не хочу, чтобы иметь в виду на BaseController подобное ,

Вопрос:

Есть ли способ для меня, чтобы поставить WrapperAction с данными, необходимыми для заполнения оболочки с? Должен ли я принять удар и начать звонить по телефону

 var tagData = GetTagData(); 
     string wrapperName = RouteData.Values["action"].ToString(); 
     base.PopulateWrapper(wrapperName, tagData); 

в каждом контроллере? Есть ли лучший способ для меня сделать это?

ответ

1

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

Ключ в том, что ваш фильтр действия тип OnActionExecuted, который работает после код завершения действия, но до того выполняется вид. Поэтому метод фильтра может основываться на том, что имело место в методе действия.

Для достижения вашего требования создайте переменную tagData в базовом контроллере, чтобы унаследованные от нее контроллеры могли заполнить ее, если это необходимо.

Затем в фильтре действия вам просто нужно что-то вроде

if (tagData == null) 
    baseController.PopulateWrapper(wrapper) 
else 
    baseController.PopulateWrapper(wrapper, tagData) 

я уверен, что вы получите общее представление.

0

имхо следующим был как раз, так что я не вижу, как фильтр действия опрятнее:

public ActionResult Home() 
{ 
    PopulateWrapper(); 
    return View(); 
} 

и в базе контроллера:

public void PopulateWrapper(string wrapperName) 
{ 
    string wrapperName = RouteData.Values["action"].ToString(); 
    //... rest of populate wrapper 

тогда вы идете:

public ActionResult Home() 
{ 
    PopulateWrapper(GetTagData()); // after defining an overload in base 
    return View(); 
} 

Предполагая, что вы все еще g o способ фильтра действий, я не понимаю, почему вы вынуждаете зависимость с базой контроллера с ним, то есть почему PopulateWrapper находится в базе контроллера.

Обратите внимание, что вы также можете передавать данные в ViewData, но это хуже всего в вашем сценарии - особенно учитывая зависимость в базе контроллера.

Смежные вопросы