如何在调用View(对象模型)时确定使用哪个View

时间:2013-10-25 16:04:06

标签: c# asp.net-mvc asp.net-mvc-4 model-view-controller viewresult

首先,某些背景信息:

  • 语言 - C#
  • 平台 - .Net Framework 4.5
  • 项目类型 - ASP.Net MVC 4

我正在尝试确定MVC项目中的哪个View正在处理对以下方法的显式调用。该方法的MSDN文档位于:http://msdn.microsoft.com/EN-US/library/dd492930.aspx

protected internal ViewResult View(
    Object model
)

原作者使用View生成带有第三方库的PDF文件。我需要修改视图以包含其他信息。

问题:我无法找到要修改的视图。它们有数百种,而且(恕我直言)它们的命名和组织都很差。生成PDF的基本过程如下所示。我在第3步和第4步之间感到困惑。

  1. 实体的ID传递给ActionResult
  2. 从后备存储中检索实体
  3. 模型传递给上面提到的Controller.View方法:
    var viewModel = 查看(模型);
    var xmlText = RenderActionResultToString( viewModel );
  4. 生成的ViewResult与ControllerContext的实例一起使用,就像生成浏览器请求一样生成HTML。
  5. 生成的HTML将传递给第三方工具并转换为PDF。
  6. 我非常清楚地理解其他一切。我不明白的是,对视图(模型)的调用如何确定返回ViewResult时要使用的View文件。任何帮助非常感谢!

    我包含以下代码,以防任何人确定答案。

    ActionResult:

    public ActionResult ProposalPDF(String id, String location, bool hidePrices = false)
    {
        var proposal = _adc.Proposal.GetByKey(int.Parse(id));
    
        var opportunity = _adc.Opportunity.GetByKey(proposal.FkOpportunityId.Value);
        ViewData["AccountId"] = opportunity.FkAccountId;
        ViewData["AccountType"] = opportunity.FkAccount.FkAccountTypeId;
    
        ViewData["Location"] = location;
        ViewData["HidePrices"] = hidePrices;
        return ViewPdf(proposal);
    }
    

    ViewPDF方法:

    protected ActionResult ViewPdf(object model)
    {
        // Create the iTextSharp document.
        var document = new Document(PageSize.LETTER);
    
        // Set the document to write to memory.
        var memoryStream = new MemoryStream();
        var pdfWriter = PdfWriter.GetInstance(document, memoryStream);
        pdfWriter.CloseStream = false;
        document.Open();
    
        // Render the view xml to a string, then parse that string into an XML dom.
        var viewModel = View(model);
        var xmlText = RenderActionResultToString(viewModel);
    
        var htmlPipelineContext = new HtmlPipelineContext();
        htmlPipelineContext.SetTagFactory(Tags.GetHtmlTagProcessorFactory());
    
        //CSS stuff
        var cssResolver = XMLWorkerHelper.GetInstance().GetDefaultCssResolver(false);
        var cssResolverPipeline = new CssResolverPipeline(cssResolver, new HtmlPipeline(htmlPipelineContext, new PdfWriterPipeline(document, pdfWriter)));
    
        var xmlWorker = new XMLWorker(cssResolverPipeline, true);
        var xmlParser = new XMLParser(xmlWorker);
    
        xmlParser.Parse(new StringReader(xmlText));
    
        // Close and get the resulted binary data.
        document.Close();
    
        var buffer = new byte[memoryStream.Position];
        memoryStream.Position = 0;
        memoryStream.Read(buffer, 0, buffer.Length);
    
        // Send the binary data to the browser.
        return new BinaryContentResult(buffer, "application/pdf");
    }
    

    RenderActionResultToString辅助方法:

    protected string RenderActionResultToString(ActionResult result)
    {
        // Create memory writer.
        var sb = new StringBuilder();
        var memWriter = new StringWriter(sb);
    
        // Create fake http context to render the view.
        var fakeResponse = new HttpResponse(memWriter);
        var fakeContext = new HttpContext(System.Web.HttpContext.Current.Request, fakeResponse);
        var fakeControllerContext = new ControllerContext(new HttpContextWrapper(fakeContext), this.ControllerContext.RouteData, this.ControllerContext.Controller);
        var oldContext = System.Web.HttpContext.Current;
        System.Web.HttpContext.Current = fakeContext;
    
        // Render the view.
        result.ExecuteResult(fakeControllerContext);
    
        // Restore data.
        System.Web.HttpContext.Current = oldContext;
    
        // Flush memory and return output.
        memWriter.Flush();
        return sb.ToString();
    }
    

3 个答案:

答案 0 :(得分:1)

确定将使用哪个视图模板的逻辑位于从调用返回的ViewResult

var viewModel = View(model);

如何选择视图取决于配置的ViewEngine,但它将使用当前的AreaControllerAction路由值来确定应该是哪个视图提供服务。

ProposalPDF操作的路由值取决于路由的配置方式,但假设默认值,操作路由值为ProposalPDF,控制器路由值将为名称此操作所在的控制器类(减去控制器后缀),该区域将是控制器所在的区域文件夹,如果在默认控制器文件夹中,则为空字符串值。然后使用这些路径值,将使用以下约定在Views文件夹中查找视图

~/Views/{Area}/{Controller}/{View}.cshtml

总有 Glimpse 可以帮助提供运行时诊断,例如哪个View文件用于提供返回的页面,虽然我不知道这会怎样查看在内部执行ViewResult以提供文件内容的时间。

答案 1 :(得分:1)

我不是确切地确定你在问什么,但是,当你致电View(model)时,所选择的视图是基于惯例的。

以下是一个例子:

public class HerbController : Controller {
    public ActionResult Cilantro(SomeType model) {
        return View(model)
    }
}

这将在名为Cilantro.cshtml的文件夹(Views / Herb / Cilantro.cshtml)中查找名为Herb的视图文件。该框架还将查看Shared目录,以防它是一个旨在跨多个结果共享的视图。

但是,您可能还需要查看Global.asax文件,以查看是否为视图引擎设置了任何自定义视图路径。我上面给出的示例基于ASP.NET MVC的默认约定。如果需要,您可以覆盖它们以更好地满足您的需求。

答案 2 :(得分:1)

视图的约定是它们位于以控制器命名的文件夹中(没有“Controller”),并且该文件夹中的.cshtml文件以调用操作命名。在你的情况下,那应该是:

~/Views/[Controller]/ProposalPdf.cshtml