asp.net-mvc – 从MVC中的控制器确定部分视图的模型
|
我目前的问题是我有一个局部的看法,我想确定它正在使用什么型号。 我不得不处理我的项目的一些奇怪的情况,所以我会尝试在这里概述,也许有人可以提供一个更好的方法来做到这一点。 我正在设计像Google iGoogle页面。具有多个小部件的主页面,可以移动或根据需要进行配置。当前系统将实际的小部件的数据异步地查看POST到我的应用程序中的控制器。该控制器将呈现可以返回(然后加载到页面视图JQUERY)的HTML的部分视图,或仅存储在数据库中的直接HTML / JavaScript。 这对我来说工作正常,我有一个模型,其中包含通过数据库描述的选项的字典,然后由部分视图使用。当我想将数据传递给部分视图时,问题出现了。我可以想出的最好的解决办法是让控制器确定所使用的部分视图中的哪个模型,具有填充模型的一些功能,然后将其与局部视图一起传递到将使其变为控制器内的HTML。 我意识到这是一个奇怪的场景,MVC(层是混合…)和任何关于基础设计的建议,或执行这将非常感谢。 我目前使用的是MVC3 / Razor。随时问任何其他问题。 解决方法我原型化了一个可能的解决方案,因为它似乎是一个有趣的问题。我希望对你有用。楷模 一,模型。我决定创建两个“小工具”,一个是新闻,一个是时钟。 public class NewsModel
{
public string[] Headlines { get; set; }
public NewsModel(params string[] headlines)
{
Headlines = headlines;
}
}
public class ClockModel
{
public DateTime Now { get; set; }
public ClockModel(DateTime now)
{
Now = now;
}
}
调节器 我的控制器不了解任何意见。它所做的是返回单个模型,但是该模型可以根据视图的要求动态获取正确的模型。 public ActionResult Show(string widgetName)
{
var selector = new ModelSelector();
selector.WhenRendering<ClockModel>(() => new ClockModel(DateTime.Now));
selector.WhenRendering<NewsModel>(() => new NewsModel("Headline 1","Headline 2","Headline 3"));
return PartialView(widgetName,selector);
}
使用代表,以便仅在实际使用正确的模型时创建/提取正确的模型。 ModelSelector 控制器使用的ModelSelector非常简单 – 只需保留一个代理包来创建每个模型类型: public class ModelSelector
{
private readonly Dictionary<Type,Func<object>> modelLookup = new Dictionary<Type,Func<object>>();
public void WhenRendering<T>(Func<object> getter)
{
modelLookup.Add(typeof(T),getter);
}
public object GetModel(Type modelType)
{
if (!modelLookup.ContainsKey(modelType))
{
throw new KeyNotFoundException(string.Format("A provider for the model type '{0}' was not provided",modelType.FullName));
}
return modelLookup[modelType]();
}
}
视图 – 简单的解决方案 现在,实现视图的最简单方法是: @model MvcApplication2.ModelSelector
@using MvcApplication2.Models
@{
var clock = (ClockModel) Model.GetModel(typeof (ClockModel));
}
<h2>The time is: @clock.Now</h2>
你可以在这里结束并使用这种方法。 意见 – 更好的解决方案 这很丑陋我希望我的意见如下: @model MvcApplication2.Models.ClockModel <h2>Clock</h2> @Model.Now 和 @model MvcApplication2.Models.NewsModel
<h2>News Widget</h2>
@foreach (var headline in Model.Headlines)
{
<h3>@headline</h3>
}
为了使这项工作,我不得不创建一个自定义视图引擎。 自定义视图引擎 当Razor视图被编译时,它会继承ViewPage< T>,其中T是@model。所以我们可以使用反射来确定视图想要什么类型,然后选择它。 public class ModelSelectorEnabledRazorViewEngine : RazorViewEngine
{
protected override IView CreateView(ControllerContext controllerContext,string viewPath,string masterPath)
{
var result = base.CreateView(controllerContext,viewPath,masterPath);
if (result == null)
return null;
return new CustomRazorView((RazorView) result);
}
protected override IView CreatePartialView(ControllerContext controllerContext,string partialPath)
{
var result = base.CreatePartialView(controllerContext,partialPath);
if (result == null)
return null;
return new CustomRazorView((RazorView)result);
}
public class CustomRazorView : IView
{
private readonly RazorView view;
public CustomRazorView(RazorView view)
{
this.view = view;
}
public void Render(ViewContext viewContext,TextWriter writer)
{
var modelSelector = viewContext.ViewData.Model as ModelSelector;
if (modelSelector == null)
{
// This is not a widget,so fall back to stock-standard MVC/Razor rendering
view.Render(viewContext,writer);
return;
}
// We need to work out what @model is on the view,so that we can pass the correct model to it.
// We can do this by using reflection over the compiled views,since Razor views implement a
// ViewPage<T>,where T is the @model value.
var compiledViewType = BuildManager.GetCompiledType(view.ViewPath);
var baseType = compiledViewType.BaseType;
if (baseType == null || !baseType.IsGenericType)
{
throw new Exception(string.Format("When the view '{0}' was compiled,the resulting type was '{1}',with base type '{2}'. I expected a base type with a single generic argument; I don't know how to handle this type.",view.ViewPath,compiledViewType,baseType));
}
// This will be the value of @model
var modelType = baseType.GetGenericArguments()[0];
if (modelType == typeof(object))
{
// When no @model is set,the result is a ViewPage<object>
throw new Exception(string.Format("The view '{0}' needs to include the @model directive to specify the model type. Did you forget to include an @model line?",view.ViewPath));
}
var model = modelSelector.GetModel(modelType);
// Switch the current model from the ModelSelector to the value of @model
viewContext.ViewData.Model = model;
view.Render(viewContext,writer);
}
}
}
视图引擎注册在Global.asax.cs中: ViewEngines.Engines.Clear(); ViewEngines.Engines.Add(new ModelSelectorEnabledRazorViewEngine()); 渲染 我的家庭视图包括以下几行来测试它: @Html.Action("Show","Widget",new { widgetName = "Clock" })
@Html.Action("Show",new { widgetName = "News" }) (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net-mvc – Kendo Grid Edit InLine Custom Validation
- asp.net – NuGet:’X’已经有一个依赖定义为’Y’
- asp.net-web-api – 如何使用OWIN自动主机的web api来提供i
- asp.net – 当使用HttpContextScoped()时,StructureMap不会
- asp.net-mvc – 具有服务层和存储库层的ASP.NET MVC,应该在
- asp.net-mvc – 使用IIS7.5将网站中的URL绑定到另一个网站控
- ASP.NET中的401.2的customerrors
- asp.net-mvc-2 – 我可以从global.asax重定向到控制器操作吗
- 在ASP.NET MVC Core控制器的构造函数中设置ViewBag属性
- asp.net – VS 2010 Web.config转换进行调试
- asp.net-mvc – Request.GetOwinContext在单元测
- asp.net-mvc-4 – Require.js优化vs asp.net mvc
- asp.net – 在asp:超链接中分配声明值的问题 错
- asp.net-mvc-4 – 如何在mvc4中将Json字符串发送
- asp.net – MS Chart控件创建的临时文件应该放在
- asp.net – 是否有可能欺骗或重用VIEWSTATE或检测
- asp.net-mvc – 运行时错误没有为扩展名’.cshtm
- asp.net – 如果Ninject尚未绑定,如何在Ninject中
- 如何指导获取一个经典的asp应用程序在IIS 7.0下工
- asp.net-mvc – 用Moq Mocking HttpContextBase
