0

まず、いくつかのコンテキスト:

  • 言語 - C#
  • プラットフォーム - .Net Framework 4.5
  • プロジェクトの種類 - ASP.Net MVC 4

MVC プロジェクトのどのビューが次のメソッドへの明示的な呼び出しを処理しているかを判断しようとしています。メソッドの MSDN ドキュメントはこちら: http://msdn.microsoft.com/EN-US/library/dd492930.aspx

protected internal ViewResult View(
    Object model
)

元の作成者はビューを使用して、サードパーティ ライブラリで PDF ファイルを生成しています。ビューを変更して追加情報を含める必要があります。

問題: 変更するビューを見つけるのに苦労しています。それらは何百もありますが、(IMHO)名前も整理も不十分です。PDF を生成する基本的なプロセスは次のようになります。ステップ3と4の間で混乱しています。

  1. Entity の ID が ActionResult に渡される
  2. エンティティはバッキング ストアから取得されます
  3. モデルは前述の Controller.View メソッドに渡さ
    ます
    var xmlText = RenderActionResultToString( viewModel );
  4. 結果の ViewResult は ControllerContext のインスタンスと共に使用され、ブラウザーによって要求されたかのように HTML を生成します。
  5. 結果の HTML はサードパーティ ツールに渡され、PDF に変換されます。

私は他のすべてを非常に明確に理解しています。私が理解していないのは、View(model)への呼び出しが、ViewResult を返すときに使用するビュー ファイルを決定する方法です。どんな助けでも大歓迎です!

誰かが答えを判断するのに役立つ場合に備えて、以下のコードを含めています。

アクション結果:

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();
}
4

3 に答える 3

1

The logic to determine which view template will be used is in the ViewResult that is returned from the call

var viewModel = View(model);

And how the view is selected is determined by the configured ViewEngine(s), but it will use the current Area, Controller and Action route values to determine what view should be served.

What the route values are for the ProposalPDF action will depend on how your routing is configured, but assuming the defaults, the action route value will be ProposalPDF, the controller route value will be the name of the controller class in which this action resides (minus the Controller suffix) and the area will be the area folder in which the controller lives, with a value of empty string if in the default controller folder. Then using these route values, a view will be looked up in the Views folder using the following convention

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

There is always Glimpse that can help with providing runtime Diagnostics too, such as which View file was used to serve up the returned page, although I'm not sure how this would look when a ViewResult is executed internally to provide the contents of a file.

于 2013-10-25T16:12:12.867 に答える
1

あなたが何を求めているのか正確にはわかりませんが、View(model)選択されたビューを呼び出すときは、規則に基づいています。

次に例を示します。

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

これにより、 (Views/Herb/Cilantro.cshtml)Cilantro.cshtmlというフォルダーで呼び出されるビュー ファイルが検索されます。HerbフレームワークはShared、複数の結果で共有されることを意図したビューである場合、ディレクトリも検索します。

ただし、Global.asaxファイルを調べて、ビュー エンジン用に設定されているカスタム ビュー パスがあるかどうかを確認することもできます。上記の例は、ASP.NET MVC の既定の規則に基づいています。必要に応じて、ニーズに合わせてオーバーライドできます。

于 2013-10-25T16:12:30.290 に答える
1

ビューの慣例では、ビューはコントローラーにちなんで名付けられたフォルダー ("Controller" なし) にあり、そのフォルダー内の .cshtml ファイルは呼び出しアクションにちなんで名付けられます。あなたの場合、それは次のようになります。

~/Views/[Controller]/ProposalPdf.cshtml
于 2013-10-25T16:14:48.017 に答える