【问题标题】:ASP.NET vNext. General editor templateASP.NET vNext。通用编辑器模板
【发布时间】:2015-11-20 17:46:04
【问题描述】:

在 MVC 5 中,我可以通过创建自定义 Object.cshtml 来自定义通用编辑器模板。

但我在 MVC 6 beta8 中找不到这种行为。

问题:如何在 MVC 6 中自定义通用编辑器模板?

更新:

似乎这个功能是硬编码的。 DefaultEditorTemplates.cs

【问题讨论】:

    标签: asp.net razor asp.net-core asp.net-core-mvc


    【解决方案1】:

    基于 DefaultEditorTemplates 类,我制作了我的 TagHelper。

    也许对某人有用。

    ModelTagHelper.cs

    [HtmlTargetElement("div", Attributes = ForAttributeName)]
    public class ModelTagHelper : TagHelper
    {
        protected const string ForAttributeName = "asp-for";
        protected const string ObjectViewPath = "~/Views/Shared/Object.cshtml";
    
        [HtmlAttributeNotBound]
        [ViewContext]
        public ViewContext ViewContext { get; set; }
    
        [HtmlAttributeName(ForAttributeName)]
        public ModelExpression For { get; set; }
    
        public override int Order => -1000;
    
        protected object Model => For.Model;
    
        protected IHtmlGenerator HtmlGenerator { get; }
        protected IViewEngine ViewEngine { get; }
        protected ITempDataProvider TempDataProvider { get; }
        protected IHttpContextAccessor HttpContextAccessor { get; }
    
        public ModelTagHelper(
            ICompositeViewEngine viewEngine, 
            ITempDataProvider tempDataProvider,
            IHttpContextAccessor httpContextAccessor,
            IHtmlGenerator generator)
        {
            HtmlGenerator = generator;
            ViewEngine = viewEngine;
            TempDataProvider = tempDataProvider;
            HttpContextAccessor = httpContextAccessor;
        }
    
        protected virtual ActionContext CreateActionContext() => new ActionContext(HttpContextAccessor.HttpContext, new RouteData(), new ActionDescriptor());
        protected virtual ViewDataDictionary CreateViewDataDictionary() => new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary());
    
        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
    
            if (output == null)
            {
                throw new ArgumentNullException(nameof(output));
            }
    
            using (var sw = new StringWriter())
            {
                var viewDataDictionary = CreateViewDataDictionary();
                viewDataDictionary.Model = Model;
    
                var actionContext = CreateActionContext();
                var viewResult = ViewEngine.FindPartialView(actionContext, ObjectViewPath);
                if (!viewResult.Success)
                {
                    throw new FileNotFoundException("Cannot find the file", ObjectViewPath);
                }
                var viewContext = new ViewContext(
                    actionContext,
                    viewResult.View,
                    viewDataDictionary,
                    new TempDataDictionary(HttpContextAccessor, TempDataProvider),
                    sw, new HtmlHelperOptions { ClientValidationEnabled = true });
                viewResult.View.RenderAsync(viewContext).Wait();
                sw.Flush();
    
                output.Content.SetContent(new HtmlString(sw.ToString()));
            }
        }
    
    }
    

    Object.cshmtl

    @using Microsoft.AspNet.Mvc.ViewFeatures
    @{
    var tplInfo = ViewContext.ViewData.TemplateInfo;
    
    Func<ModelExplorer, TemplateInfo, bool> ShouldShow =
        (modelExplorer, templateInfo) =>
        modelExplorer.Metadata.ShowForEdit &&
        !modelExplorer.Metadata.IsComplexType &&
        !templateInfo.Visited(modelExplorer);
    
    var properties = from property in ViewData.ModelExplorer.Properties
                     let propertyMetadata = property.Metadata
                     where ShouldShow(property, tplInfo)
                     select propertyMetadata;
    
    }
    @foreach (var propertyMetadata in properties)
    {
    if (propertyMetadata.HideSurroundingHtml)
    {
        @Html.Editor(propertyMetadata.PropertyName)
    }
    else
    {
        var label = Html.Label(propertyMetadata.PropertyName, labelText: null, htmlAttributes: null);
        if (!string.IsNullOrEmpty(label.ToString()))
        {
            <div class="editor-label">
                @label
            </div>
        }
        <div class="editor-field">
            @Html.Editor(propertyMetadata.PropertyName)
            @Html.ValidationMessage(propertyMetadata.PropertyName)
        </div>
    }
    }
    

    MyView.cshtml

    <div asp-for="@Model"></div>
    

    【讨论】:

      【解决方案2】:

      Asp.Net-5 带来了一个名为“TagHelpers”的新功能。

      您可以在默认的 MVC6 共享 _Layout.cshtml 页面中看到它们的工作,其中的“环境”标签会根据运行时环境(开发、登台、生产等)产生不同的输出。

      您将看到“Microsoft.AspNet.MVC.TagHelpers...”包加载到解决方案资源管理器的“参考”部分中的 DNX 4.5.1 和 DNX Core 5.0 框架部分中。

      看起来 TagHelpers 的设计目的是替代“模板”。

      在这里快速概览:Wildermuth

      还有两篇更深入的文章:MSDNMSDN Mag - 两篇文章

      希望对你有所帮助。

      【讨论】:

      • 标签助手的设计目的不是替代模板,而是使用 @Htmlhelpers 和 co。在 HTML 中。支持作为真正 XML 的 HTML。
      • ProfK——不是指“项目模板”;但是,正如您所指出的,@Html 助手生成的模板。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-10
      • 2011-05-14
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      相关资源
      最近更新 更多