asp.net-mvc – 构建MVC CMS
我需要一个简单的功能来在这些页面上添加页面/更改内容.我已经看过n2和其他预构建的CMS工具,但这些是我需要的简单CMS功能的高级方法.
什么是最好的方法?我已经有一个MVC应用程序,我想添加/构建一个简单的功能,如: >指定模板 不知道从哪里开始. 任何信息非常感谢. 这适用于.NET MVC 解决方法
假设你正在使用ASP.NET MVC而你想保持简单,那么这样的事情如何:
public abstract class TemplateBase { public abstract string TemplateName { get; } } public class SingleColumnTemplate : TemplateBase { public override string TemplateName { get { return "Single-column page"; } } public AreaContainer CenterColumn { get; protected set; } public SingleColumnTemplate() { CenterColumn = new AreaContainer("Center column"); } } public class TwoColumnTemplate : TemplateBase { public override string TemplateName { get { return "Two-column page"; } } public AreaContainer LeftColumn { get; protected set; } public AreaContainer RightColumn { get; protected set; } public TwoColumnTemplate() { LeftColumn = new AreaContainer("Left column"); RightColumn = new AreaContainer("Right column"); } } // TODO Add more template types public class AreaContainer { public string ContainerName { get; set; } public IList<AreaBase> Areas { get; protected set; } public AreaContainer(string name) { ContainerName = name; Areas = new List<AreaBase>(); } } public abstract class AreaBase { public abstract string AreaName { get; } } public class HtmlArea : AreaBase { public override string AreaName { get { return "HTML content"; } } public string HtmlContent { get; set; } } // TODO Add more area types public class Page { public int Id { get; set; } public string Title { get; set; } public TemplateBase Template { get; set; } } 用于编辑现有页面的控制器操作可能类似于: public class PageAdminController : Controller { [HttpGet] ActionResult Edit(int id) { var page = GetPageFromStorageById(id); // TODO If the page is not found,issue 404 return View(page); } // ... } 在视图(Views / PageAdmin / Edit.aspx)中,应该强烈键入ViewPage< Page>,您可以使用HtmlHelper.EditorFor(…)方法呈现相应的模板视图,前提是您已创建了部分模板视图查看每种模板类型: <!-- Inside the edit view for Page (Edit.aspx) --> <%: Html.HiddenFor(m => m.Id) %> <%: Html.EditorFor(m => m.Title) %> <%: Html.EditorFor(m => m.Template) %> 在Views / PageAdmin / EditorTemplates文件夹中,您将为每个模板和区域类型放置部分编辑视图(即SingleColumnTemplate.ascx,TwoColumnTemplate.ascx和HtmlArea.ascx).您可能还想为AreaContainer创建局部视图. 至于接收编辑过的页面的控制器动作,事情会变得复杂一些.由于Page有一个类型为TemplateBase的属性,它是一个抽象类,因此DefaultModelBinder不知道如何填充它.您可以通过编写自定义模型绑定器来解决这个问题,该绑定器以某种方式“知道”要实例化的实现类.怎么会知道呢?我能想到的一个选项是在视图中包含一个隐藏字段,其中包含页面模板的实际运行时类型的名称.我想这是一个黑客攻击,但是因为你在简单之后,我认为它会好起来的.在这种情况下,只需在TemplateBase类中包含一个名为RuntimeTypeName的属性: public string RuntimeTypeName { get { return GetType().FullName; } } 由于它只是调用GetType(),它是默认情况下被所有类型覆盖的虚方法,因此它将返回运行时模板类型的名称. 然后,您必须确保为TemplateBase实现创建的部分视图包含TemplateBase.RuntimeTypeName属性的(隐藏)字段.换句话说,在SingleColumnTemplate.ascx和TwoColumnTemplate.ascx中,您将拥有以下行: <%: Html.HiddenFor(m => m.RuntimeTypeName) %> 利用此信息创建正确类型的模板的模型绑定器可能如下所示: /// <summary> /// Model binder hack that builds upon the DefaultModelBinder,/// but that can detect the "proper" subclass/implementing class /// type for a model,assuming the name of that type is contained /// in a field called "RuntimeTypeName". /// </summary> public class InheritanceSupportingModelBinder : DefaultModelBinder { // Assume that the name of the field that contains the // runtime type name is called "RuntimeTypeName" public const string RuntimeTypeNameField = "RuntimeTypeName"; private Type RuntimeType { get; set; } // This method is called by the DefaultModelBinder to find out which // properties of the current model that it should attempt to bind protected override PropertyDescriptorCollection GetModelProperties( ControllerContext controllerContext,ModelBindingContext bindingContext) { // If we have found out the runtime type of the model through // looking at the "special" field above,use the properties of that type. // Otherwise,use the default behavior. if (RuntimeType != null) { return TypeDescriptor.GetProperties(RuntimeType); } else { return base.GetModelProperties(controllerContext,bindingContext); } } // This method is called by the DefaultModelBinder when it // tries to create an instance of the model class. If the // class is abstract,an exception will be thrown. Therefore // we try to read the name of the actual type from the // RuntimeTypeName (hidden) field and return an instance of that type. protected override object CreateModel(ControllerContext controllerContext,ModelBindingContext bindingContext,Type modelType) { if (bindingContext.ValueProvider.ContainsPrefix( bindingContext.ModelName + "." + RuntimeTypeNameField)) { var result = bindingContext.ValueProvider.GetValue( bindingContext.ModelName + "." + RuntimeTypeNameField); if (result != null && !string.IsNullOrEmpty(result.AttemptedValue)) { // Check that the type indicated by the hidden field is really // a subclass of (or implementing) the indicated base class var tempType = Type.GetType(result.AttemptedValue); if (modelType.IsAssignableFrom(tempType)) { RuntimeType = modelType = tempType; } } } return base.CreateModel(controllerContext,bindingContext,modelType); } } 免责声明:我自己是ASP.NET MVC的初学者,所以这个模型绑定器可能有问题.我通过查看DefaultModelBinder的源代码并通过反复试验将它放在一起.这只是一个例子,但根据我的(快速和肮脏)测试它似乎工作. 当然,您需要在Global.asax中注册它才能启动它: ModelBinders.Binders.Add( typeof(TemplateBase),new InheritanceSupportingModelBinder()); 但是我们没有完成!请记住,AreaContainer.Areas集合的类型为IList< AreaBase> – 并且由于AreaBase也是一个抽象类,我们必须应用相同的hack才能正确绑定它.也就是说,将RuntimeTypeName属性添加到AreaBase类,并在Global.asax中为AreaBase类注册我们的自定义模型绑定器. 如果到目前为止我们已经执行了所有这些步骤,我们可以在PageAdminController上使用一个action方法来处理页面的编辑,如下所示: [HttpPost] public ActionResult Edit(Page page) { if (!ModelState.IsValid) { return View(page); } // TODO Save page to database or whatever // TODO Redirect to page index } 创建新页面的操作方法留作练习,不应该那么困难(用户从列表中选择模板,显示正确的表单,如上所述的后处理操作). 显示页面应该是微不足道的,只需使用HtmlHelper.DisplayFor(…)而不是EditorFor(…),创建相应的部分视图并进行设置. 对于WYSIWYG内容编辑,您可能希望使用第三方组件. CKEditor,TinyMCE,YUI Rich Text Editor和Telerik Editor是一些例子. 这是我对此的看法!欢迎所有评论;正如我所提到的,我自己正在学习ASP.NET MVC,如果我的错误被那些了解得更好的人指出,那将会很棒. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- ASP.NET Core中的Startup.cs中的asp.net-core – Kestrel关
- asp.net – 在SDL Tridion 2011中将JSON文件上传为多媒体组
- asp.net – 如何告诉RadioButtonList不生成表
- Asp.net Core 使用Jenkins + Dockor 实现持续集成、自动化部
- 如何在asp.net中从c#运行javascript
- asp.net – UserControl Viewstate在回发后丢失所有值
- asp.net – 在运行时更改SqlDataSource.SelectCommand会破坏
- asp.net-mvc – MVC模型绑定到集合不以0索引开头的集合
- asp.net-web-api – 使用ASP.NET WebAPI消费Atlassian Webh
- asp.net – Global.asax中的事件未触发
- asp.net CustomValidator从不触发OnServerValida
- 在两个应用程序中拆分ASP.NET应用程序 – 处理共
- 如何减少ASP.net MVC 2中的首次加载时间?
- asp.net-mvc-4 – ASP.NET MVC 4中的单页面应用程
- asp.net – 如何在web.config中加密连接
- asp.net-mvc – 使用ViewModel模式与MVC 2强类型
- asp.net – 带有OWIN的Web API会为HttpMessageIn
- asp.net – PreRenderComplete和SaveState之间的
- asp.net – <%%>和<%=%>之间有什么区别?
- asp.net – 具有默认值的TextBox