2010-09-08 62 views
2

背景:是否可以在Action Filter中使用Action Method中的数据?

我们正在与HTML文件中提供 - “包装” - 从我们的客户,在其中我们需要注入我们生产的内容。他们对不同的页面有不同的包装,我们必须将相应的内容注入到它们在包装中提供的特殊标签中。

包装文件名称对应于操作方法的名称。因此,对于下面的示例,将执行一个自定义操作筛选器,该筛选器将确定包装器的名称,然后调用BaseController中的一个方法(每个控制器都实现该方法),该方法将加载包装器并向其中注入内容。

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

我把这个在一个ActionFilter的原因是因为我不想被调用BaseController的方法来填充在需要包装的每一个动作方法的包装。我认为这是更为整洁,与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; 
    } 

的姿态的尴尬:

然而,现在有了一个新的要求。在wr中有一些新的标签apper,我需要填充,并且我必须用不同的数据填充它们,具体取决于调用封装器的操作方法。该数据是在操作方法中确定的,但数据需要在由WrapperAction调用的PopulateWrapper方法中使用。

我现在需要有类似的方法来

AppHelper.PopulateWrapperTags(wrapper, this.TagData);

,我需要有某种方式来填充数据BaseController的财产tagdata进行。我可以在操作方法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(); 
} 

假设你还是克o操作过滤器的方式,我不明白你为什么强制与它的控制器基地的依赖关系,即为什么PopulateWrapper是在控制器基地。

请注意,您还可以传递ViewData的数据,但最糟糕的感觉在你的情况 - 特别是鉴于控制器基地的依赖。

相关问题