How does Asp.net Core renders a view

2019-01-25 15:28发布

问题:

How does MVC 6 renders a view. What's the actual method in Razor ViewEngine that generates the html output? Also if possible please explain the process of rendering a view.

May be you could point me to a file on mvc source on github. thanks!

回答1:

Here is a complete solution of what you are looking for. I used dependency injection to get the HtmlHelper in the controller. You can inject your own helper if you want too.

using Microsoft.AspNet.Html.Abstractions;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Mvc.ViewEngines;
using Microsoft.AspNet.Mvc.ViewFeatures;
using Microsoft.AspNet.Mvc.ViewFeatures.Internal;
using Microsoft.Extensions.WebEncoders;
using System.ComponentModel.DataAnnotations;
using System;

 public class MyController : Controller
 {
    private readonly IHtmlGenerator htmlGenerator;
    ICompositeViewEngine viewEngine;
    IModelMetadataProvider metadataProvider;
    private readonly IHtmlHelper helper;
    IHtmlEncoder htmlEncoder;
    IUrlEncoder urlEncoder;
    IJavaScriptStringEncoder javaScriptStringEncoder;

    public MyController(IHtmlHelper helper, IHtmlGenerator htmlGenerator, ICompositeViewEngine viewEngine, IModelMetadataProvider metadataProvider, IHtmlEncoder htmlEncoder, IUrlEncoder urlEncoder, IJavaScriptStringEncoder javaScriptStringEncoder)
    {

        this.htmlGenerator = htmlGenerator;
        this.viewEngine = viewEngine;
        this.metadataProvider = metadataProvider;
        this.htmlEncoder = htmlEncoder;
        this.urlEncoder = urlEncoder;
        this.javaScriptStringEncoder = javaScriptStringEncoder;
        this.helper = helper;
    }

    [HttpGet]
    public IActionResult MyHtmlGenerator()
    {
        MyViewModel temp = new MyViewModel();


        var options = new HtmlHelperOptions();
        options.ClientValidationEnabled = true;

        ViewDataDictionary<MyViewModel> dic = new ViewDataDictionary<MyViewModel>(this.metadataProvider, new ModelStateDictionary());

        ViewContext cc = new ViewContext(ActionContext, new FakeView(), dic, TempData, TextWriter.Null, options);

        var type = typeof(MyViewModel);
        var metadata = this.metadataProvider.GetMetadataForType(type);


        ModelExplorer modelEx = new ModelExplorer(this.metadataProvider, metadata, temp);
        ViewData["Description"] = "test desc";
        ViewData["Id"] = 1;

        this.ViewData = new ViewDataDictionary(this.metadataProvider, new ModelStateDictionary());

        IHtmlHelper<MyViewModel> dd = new HtmlHelper<MyViewModel>(this.htmlGenerator, this.viewEngine, this.metadataProvider, this.htmlEncoder, this.urlEncoder, this.javaScriptStringEncoder);
        ((ICanHasViewContext)dd).Contextualize(cc);
        dd.ViewContext.ViewData = this.ViewData;

        var desc = GetString(dd.TextBoxFor(m => m.ID));
        var ID = GetString(dd.TextBoxFor(m => m.Description));

        // Do whatever you want with the ID and desc

        return new ContentResult() { Content = ID + desc };

    }

    public static string GetString(IHtmlContent content)
    {
        var writer = new System.IO.StringWriter();
        content.WriteTo(writer, new HtmlEncoder());
        return writer.ToString();
    }
}


public class MyViewModel : BaseAssetViewModel
{
    //  [RegularExpression(@"^-?\d{1,13}(\.\d{0,5})?$|^-?\.\d{1,5}$")]
    [Required]
    public int ID { get; set; }

    [MinLength(2)]
    public string Description { get; set; }

    // Property with no validation
    public string Other { get; set; }
}


public class FakeView : IView
{
    string IView.Path
    {
        get
        {
            throw new NotImplementedException();
        }
    }

    public Task RenderAsync(ViewContext viewContext)
    {
        throw new InvalidOperationException();
    }

    Task IView.RenderAsync(ViewContext context)
    {
        throw new NotImplementedException();
    }
}


回答2:

I don't know if this may be of help, may be you have to start to look at tag helpers:

https://github.com/DamianEdwards/TagHelperStarterWeb

they're working to a different way to create helpers that integrate in the page in a more natural way.