Sco*_*ein 93 asp.net-mvc viewdata autofac asp.net-mvc-3
在过去,我通过让所有控制器继承公共基本控制器,以全局方式将常见属性(例如当前用户)粘贴到ViewData/ViewBag上.
这使得我可以在基本控制器上使用IoC,而不仅仅是为这些数据扩展到全局共享.
我想知道是否有另一种方法将这种代码插入MVC管道?
Moh*_*imi 237
最好的方法是使用ActionFilterAttribute并在全局中注册自定义类.asax(Application_Start)
public class UserProfilePictureActionFilter : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
filterContext.Controller.ViewBag.IsAuthenticated = MembershipService.IsAuthenticated;
filterContext.Controller.ViewBag.IsAdmin = MembershipService.IsAdmin;
var userProfile = MembershipService.GetCurrentUserProfile();
if (userProfile != null)
{
filterContext.Controller.ViewBag.Avatar = userProfile.Picture;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在您的全局中注册您的自定义类.asax(Application_Start)
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalFilters.Filters.Add(new UserProfilePictureActionFilter(), 0);
}
Run Code Online (Sandbox Code Playgroud)
然后您可以在所有视图中使用它
@ViewBag.IsAdmin
@ViewBag.IsAuthenticated
@ViewBag.Avatar
Run Code Online (Sandbox Code Playgroud)
还有另一种方式
在HtmlHelper上创建扩展方法
[Extension()]
public string MyTest(System.Web.Mvc.HtmlHelper htmlHelper)
{
return "This is a test";
}
Run Code Online (Sandbox Code Playgroud)
然后您可以在所有视图中使用它
@Html.MyTest()
Run Code Online (Sandbox Code Playgroud)
Bra*_*ton 39
由于ViewBag属性根据定义与视图表示和可能需要的任何光视图逻辑相关联,因此我将创建一个基本WebViewPage并在页面初始化时设置属性.它与重复逻辑和常用功能的基本控制器的概念非常相似,但对于您的视图:
public abstract class ApplicationViewPage<T> : WebViewPage<T>
{
protected override void InitializePage()
{
SetViewBagDefaultProperties();
base.InitializePage();
}
private void SetViewBagDefaultProperties()
{
ViewBag.GlobalProperty = "MyValue";
}
}
Run Code Online (Sandbox Code Playgroud)
然后在\Views\Web.config,设置pageBaseType属性:
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="MyNamespace.ApplicationViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
</namespaces>
</pages>
</system.web.webPages.razor>
Run Code Online (Sandbox Code Playgroud)
Nic*_*rdt 22
我没有尝试过,但您可能会考虑注册视图,然后在激活过程中设置视图数据.
由于视图是即时注册的,因此注册语法无法帮助您连接到Activated事件,因此您需要在以下位置进行设置Module:
class SetViewBagItemsModule : Module
{
protected override void AttachToComponentRegistration(
IComponentRegistration registration,
IComponentRegistry registry)
{
if (typeof(WebViewPage).IsAssignableFrom(registration.Activator.LimitType))
{
registration.Activated += (s, e) => {
((WebViewPage)e.Instance).ViewBag.Global = "global";
};
}
}
}
Run Code Online (Sandbox Code Playgroud)
这可能是我的"唯一工具是锤子"式建议之一; 可能有更简单的MVC方法来实现它.
编辑:替代,更少的代码方法 - 只需附加到控制器
public class SetViewBagItemsModule: Module
{
protected override void AttachToComponentRegistration(IComponentRegistry cr,
IComponentRegistration reg)
{
Type limitType = reg.Activator.LimitType;
if (typeof(Controller).IsAssignableFrom(limitType))
{
registration.Activated += (s, e) =>
{
dynamic viewBag = ((Controller)e.Instance).ViewBag;
viewBag.Config = e.Context.Resolve<Config>();
viewBag.Identity = e.Context.Resolve<IIdentity>();
};
}
}
}
Run Code Online (Sandbox Code Playgroud)
编辑2:另一种直接来自控制器注册码的方法:
builder.RegisterControllers(asm)
.OnActivated(e => {
dynamic viewBag = ((Controller)e.Instance).ViewBag;
viewBag.Config = e.Context.Resolve<Config>();
viewBag.Identity = e.Context.Resolve<IIdentity>();
});
Run Code Online (Sandbox Code Playgroud)
小智 17
布兰登的帖子是合适的.作为事实上,我会一步借此,说你应该只添加您的常见对象作为属性的的基础WebViewPage,所以你不必在每一个视图从ViewBag投项目.我这样做我的CurrentUser设置.
您可以使用自定义ActionResult:
public class GlobalView : ActionResult
{
public override void ExecuteResult(ControllerContext context)
{
context.Controller.ViewData["Global"] = "global";
}
}
Run Code Online (Sandbox Code Playgroud)
甚至是ActionFilter:
public class GlobalView : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.Result = new ViewResult() {ViewData = new ViewDataDictionary()};
base.OnActionExecuting(filterContext);
}
}
Run Code Online (Sandbox Code Playgroud)
有一个MVC 2项目开放,但这两种技术仍然适用于微小的变化.
您不必搞乱动作或更改模型,只需使用基本控制器,然后从布局viewcontext投射现有的控制器即可。
使用所需的通用数据(标题/页面/位置等)创建基本控制器并进行动作初始化...
public abstract class _BaseController:Controller {
public Int32 MyCommonValue { get; private set; }
protected override void OnActionExecuting(ActionExecutingContext filterContext) {
MyCommonValue = 12345;
base.OnActionExecuting(filterContext);
}
}
Run Code Online (Sandbox Code Playgroud)
确保每个控制器都使用基本控制器...
public class UserController:_BaseController {...
Run Code Online (Sandbox Code Playgroud)
从_Layout.cshml页面的视图上下文中投射现有的基本控制器。
@{
var myController = (_BaseController)ViewContext.Controller;
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以从布局页面引用基本控制器中的值。
@myController.MyCommonValue
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
69619 次 |
| 最近记录: |