কোনও এএসপি.নেট এমভিসি ভিউকে স্ট্রিং হিসাবে কীভাবে রেন্ডার করবেন?


485

আমি দুটি ভিন্ন দর্শন আউটপুট করতে চাই (একটি স্ট্রিং হিসাবে যা ইমেল হিসাবে প্রেরণ করা হবে), এবং অন্যটি পৃষ্ঠাটি ব্যবহারকারীর কাছে প্রদর্শিত হয়।

এটিএসপি নেট নেট এমভিসি বিটাতে কি সম্ভব?

আমি একাধিক উদাহরণ চেষ্টা করেছি:

1. এএসপি.নেট এমভিসি বিটাতে স্ট্রিং-রেন্ডার পার্টিশিয়াল

আমি যদি এই উদাহরণটি ব্যবহার করি তবে আমি "HTTP শিরোনাম প্রেরণের পরে পুনর্নির্দেশ করতে পারছি না" receive

2. এমভিসি ফ্রেমওয়ার্ক: একটি ভিউ আউটপুট ক্যাপচার

যদি আমি এটি ব্যবহার করি তবে আমি একটি পুনর্নির্দেশতন্ত্রটি করতে অক্ষম বলে মনে হচ্ছে, কারণ এটি এমন কোনও ভিউ রেন্ডার চেষ্টা করে যা অস্তিত্বহীন। আমি যদি ভিউটি ফিরিয়ে দিই তবে এটি পুরোপুরি গণ্ডগোল হয়ে গেছে এবং একেবারেই ঠিক দেখাচ্ছে না।

আমার কাছে থাকা এই সমস্যার জন্য কারও কি কোনও ধারণা / সমাধান আছে, বা আরও ভালগুলির জন্য কোনও পরামর্শ আছে?

অনেক ধন্যবাদ!

নীচে একটি উদাহরণ দেওয়া আছে। আমি যা করার চেষ্টা করছি তা হ'ল গেটভিউ ফোরইমেল পদ্ধতি তৈরি করুন :

public ActionResult OrderResult(string ref)
{
    //Get the order
    Order order = OrderService.GetOrder(ref);

    //The email helper would do the meat and veg by getting the view as a string
    //Pass the control name (OrderResultEmail) and the model (order)
    string emailView = GetViewForEmail("OrderResultEmail", order);

    //Email the order out
    EmailHelper(order, emailView);
    return View("OrderResult", order);
}

টিম স্কট থেকে গৃহীত উত্তর (আমার দ্বারা কিছুটা পরিবর্তন এবং ফর্ম্যাট করা):

public virtual string RenderViewToString(
    ControllerContext controllerContext,
    string viewPath,
    string masterPath,
    ViewDataDictionary viewData,
    TempDataDictionary tempData)
{
    Stream filter = null;
    ViewPage viewPage = new ViewPage();

    //Right, create our view
    viewPage.ViewContext = new ViewContext(controllerContext, new WebFormView(viewPath, masterPath), viewData, tempData);

    //Get the response context, flush it and get the response filter.
    var response = viewPage.ViewContext.HttpContext.Response;
    response.Flush();
    var oldFilter = response.Filter;

    try
    {
        //Put a new filter into the response
        filter = new MemoryStream();
        response.Filter = filter;

        //Now render the view into the memorystream and flush the response
        viewPage.ViewContext.View.Render(viewPage.ViewContext, viewPage.ViewContext.HttpContext.Response.Output);
        response.Flush();

        //Now read the rendered view.
        filter.Position = 0;
        var reader = new StreamReader(filter, response.ContentEncoding);
        return reader.ReadToEnd();
    }
    finally
    {
        //Clean up.
        if (filter != null)
        {
            filter.Dispose();
        }

        //Now replace the response filter
        response.Filter = oldFilter;
    }
}

ব্যবহারের উদাহরণ

সাইট.মাস্টার অবস্থানটি পাস করে অর্ডার কনফার্মেশন ইমেলটি পেতে নিয়ামকের কাছ থেকে কল গ্রহণ করা।

string myString = RenderViewToString(this.ControllerContext, "~/Views/Order/OrderResultEmail.aspx", "~/Views/Shared/Site.Master", this.ViewData, this.TempData);

2
আপনি দৃ a়ভাবে টাইপ করা একটি দৃশ্যের সাহায্যে এটি কীভাবে ব্যবহার করতে পারেন? অর্থাৎ। আমি কীভাবে পৃষ্ঠায় একটি মডেল খাওয়াতে পারি?
কেজেনসেন

এটি ব্যবহার করতে পারবেন না এবং পরে জসনআরসাল্ট তৈরি করতে পারবেন না, কারণ শিরোনাম প্রেরণের পরে সামগ্রীর ধরণ সেট করা যাবে না (কারণ ফ্লাশ তাদের পাঠিয়ে দেয়)।
আরনিস ল্যাপসা

কারণ কোনও একক সঠিক উত্তর নেই, আমার ধারণা। :) আমি একটি প্রশ্ন তৈরি করেছি যা আমার কাছে সুনির্দিষ্ট ছিল, তবে আমি জানতাম যে এটি একটি বহুল জিজ্ঞাসাযোগ্য প্রশ্নও হবে।
ড্যান অ্যাটকিনসন

2
প্রস্তাবিত সমাধান এমভিসি 3 তে কাজ করে না
ক্যাস্পার হোল্ডাম

1
@ কিউয়া: প্রস্তাবিত সমাধানটি দুই বছরের বেশি পুরানো। আমি এটি এমভিসি 3 এর জন্য কাজ করবে বলে আশা করবো না! এছাড়াও, এখন এটি করার আরও ভাল উপায় রয়েছে।
ড্যান অ্যাটকিনসন

উত্তর:


572

এখানে আমি কী নিয়ে এসেছি এবং এটি আমার জন্য কাজ করছে। আমি আমার নিয়ামক বেস শ্রেণিতে নিম্নলিখিত পদ্ধতি (গুলি) যুক্ত করেছি। (আপনি স্থির এই পদ্ধতিগুলি অন্য কোথাও তৈরি করতে পারেন যা আমার ধারণা হিসাবে কোনও নিয়ামককে প্যারামিটার হিসাবে গ্রহণ করে)

এমভিসি 2 .অ্যাসেক্স স্টাইল

protected string RenderViewToString<T>(string viewPath, T model) {
  ViewData.Model = model;
  using (var writer = new StringWriter()) {
    var view = new WebFormView(ControllerContext, viewPath);
    var vdd = new ViewDataDictionary<T>(model);
    var viewCxt = new ViewContext(ControllerContext, view, vdd,
                                new TempDataDictionary(), writer);
    viewCxt.View.Render(viewCxt, writer);
    return writer.ToString();
  }
}

রেজার। Cshtml শৈলী

public string RenderRazorViewToString(string viewName, object model)
{
  ViewData.Model = model;
  using (var sw = new StringWriter())
  {
    var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext,
                                                             viewName);
    var viewContext = new ViewContext(ControllerContext, viewResult.View,
                                 ViewData, TempData, sw);
    viewResult.View.Render(viewContext, sw);
    viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
    return sw.GetStringBuilder().ToString();
  }
}

সম্পাদনা করুন: রেজার কোড যুক্ত হয়েছে।


31
স্ট্রিংয়ে একটি ভিউ রেন্ড করা সর্বদা "পুরো রাউটিং ধারণার সাথে সঙ্গতিপূর্ণ নয়", কারণ রাউটিংয়ের সাথে এর কোনও যোগসূত্র নেই। আমি নিশ্চিত নই কেন একটি উত্তর যে কাজ করে একটি ডাউন ভোট পেয়েছিল।
বেন লেশ

4
আমি মনে করি রেজার সংস্করণের পদ্ধতি ঘোষণা থেকে আপনার "স্ট্যাটিক" অপসারণের প্রয়োজন হতে পারে, অন্যথায় এটি কন্ট্রোলার কনটেক্সট এবং আল খুঁজে পাবে না।
মাইক

3
আপনাকে অতিরিক্ত অতিরিক্ত সাদা স্থানগুলির জন্য অপসারণের নিজস্ব পদ্ধতিটি প্রয়োগ করতে হবে। আমি আমার মাথার উপরের দিকের সেরা উপায়টি মনে করতে পারছি তা হল একটি এক্সএমএল ডকুমেন্টে স্ট্রিংটি লোড করা, তারপরে এটি আমার শেষ মন্তব্যে যে লিঙ্কটি রেখেছিল সে অনুযায়ী একটি এক্সএমএল রাইটার দিয়ে একটি স্ট্রিংয়ে আবার লিখুন। আমি সত্যিই আশা করি যে সাহায্য করে।
বেন লেশ

3
হুম কীভাবে ওয়েবএপিআই কন্ট্রোলার ব্যবহার করে এটি করা উচিত, যে কোনও পরামর্শ প্রশংসা করা হবে
আলেকজান্ডার

3
সবাইকে হাই কন্ট্রোলারদের "স্ট্যাটিক" কীওয়ার্ড দিয়ে এটিকে সাধারণ করার জন্য ব্যবহার করার জন্য আপনাকে স্ট্যাটিক ক্লাস করতে হবে এবং এর ভিতরে আপনাকে "কন্ট্রোলার কনটেক্সট" এর পরামিতি হিসাবে "এই" দিয়ে এই পদ্ধতিটি রাখতে হবে। আপনি এখানে স্ট্যাকওভারফ্লো . com/a/18978036/2318354 দেখতে পারেন ।
দিলিপ 0165

68

এই উত্তর আমার পথে হয় না। এটি মূলত https://stackoverflow.com/a/2759898/2318354 থেকে এসেছে তবে এটি সমস্ত নিয়ামকের জন্য সাধারণ করার জন্য আমি "স্ট্যাটিক" কীওয়ার্ড দিয়ে এটি ব্যবহার করার উপায়টি দেখিয়েছি।

তার জন্য আপনাকে staticক্লাস ফাইলে ক্লাস করতে হবে। (ধরুন আপনার ক্লাস ফাইলের নাম ইউটিলস.এস)

এই উদাহরণটি রেজারের জন্য।

Utils.cs

public static class RazorViewToString
{
    public static string RenderRazorViewToString(this Controller controller, string viewName, object model)
    {
        controller.ViewData.Model = model;
        using (var sw = new StringWriter())
        {
            var viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
            var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
            viewResult.View.Render(viewContext, sw);
            viewResult.ViewEngine.ReleaseView(controller.ControllerContext, viewResult.View);
            return sw.GetStringBuilder().ToString();
        }
    }
}

এখন আপনি নিয়ন্ত্রকের কাছে প্যারামিটার হিসাবে "এটি" পাস করে নিম্নলিখিত পদ্ধতিতে আপনার কন্ট্রোলার ফাইলে নেমস্পেস যুক্ত করে এই বিভাগটিকে আপনার নিয়ামক থেকে কল করতে পারেন।

string result = RazorViewToString.RenderRazorViewToString(this ,"ViewName", model);

@ সার্জি দ্বারা প্রদত্ত পরামর্শ হিসাবে এই এক্সটেনশন পদ্ধতিটি নীচে দেওয়া হিসাবে কোট্রোলার থেকেও কল করতে পারে

string result = this.RenderRazorViewToString("ViewName", model);

আমি আশা করি কোডটি পরিষ্কার এবং ঝরঝরে করে তুলতে এটি আপনার পক্ষে কার্যকর হবে।


1
চমৎকার সমাধান! একটি জিনিস, রেন্ডাররাজোরভিউটোস্ট্রিং আসলে এক্সটেনশন পদ্ধতি (কারণ আপনি এই কীওয়ার্ড দিয়ে নিয়ন্ত্রণকারী পরামিতিটি পাস করেন), সুতরাং এই এক্সটেনশন পদ্ধতিটিকে এভাবে বলা যেতে পারে: this.RenderRazorViewToString ("ViewName", মডেল);
সের্গেই

@ সের্গে হুমমম ... আমাকে সেভাবে পরীক্ষা করতে দিন, যদি আমার উত্তরটি আপডেট করে দেওয়া হয় তবে এটি ভাল হয়। যাইহোক আপনার পরামর্শের জন্য ধন্যবাদ।
দিলিপ 0165

দিলিপ ০১65৫, আমি ভ্যার ভিউরেসাল্ট = ভিউএঞ্জাইনস.এইংাইনস.ফাইন্ড পার্টিয়ালভিউ (কন্ট্রোলার.কন্ট্রোলার কনটেক্সট, ভিউনাম); এ একটি নাল রেফারেন্স ত্রুটি পেয়েছি। যদি আপনার কোন ধারণা আছে?
সিবি 4

@ সিবি 4 আমি মনে করি এটি "ভিউনাম" এর সমস্যা হতে পারে যা আপনি কার্যক্রমে চলে যাচ্ছেন। আপনার ফোল্ডার কাঠামো অনুযায়ী আপনাকে পুরো পথ দিয়ে "ভিউনাম" পাস করতে হবে। সুতরাং এই জিনিসটি দেখুন।
দিলিপ 0165

1
@ সের্গে আপনার পরামর্শের জন্য ধন্যবাদ, আমি আপনার পরামর্শ অনুসারে আমার উত্তর আপডেট করেছি যা সম্পূর্ণ সঠিক
দিলিপ ০১65৫

32

এটি আমার পক্ষে কাজ করে:

public virtual string RenderView(ViewContext viewContext)
{
    var response = viewContext.HttpContext.Response;
    response.Flush();
    var oldFilter = response.Filter;
    Stream filter = null;
    try
    {
        filter = new MemoryStream();
        response.Filter = filter;
        viewContext.View.Render(viewContext, viewContext.HttpContext.Response.Output);
        response.Flush();
        filter.Position = 0;
        var reader = new StreamReader(filter, response.ContentEncoding);
        return reader.ReadToEnd();
    }
    finally
    {
        if (filter != null)
        {
            filter.Dispose();
        }
        response.Filter = oldFilter;
    }
}

আপনার মন্তব্যের জন্য ধন্যবাদ, তবে তা কি কোনও দৃশ্যের ভিতরে উপস্থাপনের জন্য ব্যবহৃত হয় না? আমি যে প্রসঙ্গে প্রশ্নটি আপডেট করেছি তা কীভাবে ব্যবহার করতে পারি?
ড্যান অ্যাটকিনসন

দুঃখিত, এখনও গত বছর সিলভারলাইট সম্পর্কে ভাবছি যার প্রথম আরসি ছিল 0 :) আমি আজ এটি শট দিচ্ছি giving (দেখার সাথে সাথে আমি দেখার পথটির সঠিক ফর্ম্যাটটি বের করে
নিই

এটি এখনও আরসি 1
পরাজিত করেছে

পরাজিত: না, তা হয় না। যদি এটি হয় তবে আপনি কিছু ভুল করছেন।
ড্যান অ্যাটকিনসন

সঙ্গে এই একীভূত stackoverflow.com/questions/520863/... , ViewEnginesCollection যোগ সচেতনতা, partialview পপ চেষ্টা এবং এই পেয়েছিলাম stackoverflow.com/questions/520863/... । : ই
আরনিস ল্যাপসা

31

আমি একটি নতুন সমাধান পেয়েছি যা বর্তমান এইচটিপিপেক্সটেক্সট এর রেসপন্স স্ট্রিমের সাথে ঝামেলা না করে স্ট্রিংকে একটি ভিউ রেন্ডার করে (যা আপনাকে প্রতিক্রিয়াটির কন্টেন্ট টাইপ বা অন্যান্য শিরোনাম পরিবর্তন করতে দেয় না)।

মূলত, আপনি যা কিছু করেন তা হ'ল নিজেকে রেন্ডার করার জন্য একটি জাল এইচটিটিপি কনটেক্সট তৈরি করা:

/// <summary>Renders a view to string.</summary>
public static string RenderViewToString(this Controller controller,
                                        string viewName, object viewData) {
    //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(HttpContext.Current.Request, fakeResponse);
    var fakeControllerContext = new ControllerContext(
        new HttpContextWrapper(fakeContext),
        controller.ControllerContext.RouteData,
        controller.ControllerContext.Controller);

    var oldContext = HttpContext.Current;
    HttpContext.Current = fakeContext;

    //Use HtmlHelper to render partial view to fake context
    var html = new HtmlHelper(new ViewContext(fakeControllerContext,
        new FakeView(), new ViewDataDictionary(), new TempDataDictionary()),
        new ViewPage());
    html.RenderPartial(viewName, viewData);

    //Restore context
    HttpContext.Current = oldContext;    

    //Flush memory and return output
    memWriter.Flush();
    return sb.ToString();
}

/// <summary>Fake IView implementation used to instantiate an HtmlHelper.</summary>
public class FakeView : IView {
    #region IView Members

    public void Render(ViewContext viewContext, System.IO.TextWriter writer) {
        throw new NotImplementedException();
    }

    #endregion
}

এটি কন্ট্রোলসাল্ট, জসনরসাল্ট ইত্যাদির সাথে একসাথে এএসপি.এনইটি এমভিসি 1.0 এ কাজ করে (মূল এইচটিপিআরস্পোনসে শিরোনাম পরিবর্তন করা " এইচটিটিপি শিরোনাম প্রেরণের পরে সার্ভার সামগ্রীর প্রকার সেট করতে পারে না " ব্যতিক্রম)।

আপডেট: এএসপি.নেট এমভিসি ২.০ আরসিতে কোডটি কিছুটা বদলে যায় কারণ ভিউটিতে StringWriterলেখার জন্য আমাদের ব্যবহার করতে হবে ViewContext:

//...

//Use HtmlHelper to render partial view to fake context
var html = new HtmlHelper(
    new ViewContext(fakeControllerContext, new FakeView(),
        new ViewDataDictionary(), new TempDataDictionary(), memWriter),
    new ViewPage());
html.RenderPartial(viewName, viewData);

//...

এইচটিএমএলহেল্পার অবজেক্টে কোনও রেন্ডার পার্টিশিয়াল পদ্ধতি নেই। এটি সম্ভব নয় - এইচটিএমএল.রেন্ডার পার্টিশিয়াল (ভিউনাম, ভিউ ডেটা);
মার্টিনএফ 8:59

1
এএসপি.এনইটি এমভিসি রিলিজ ১.০ এ রেন্ডার পার্টিশিয়াল এক্সটেনশন পদ্ধতি রয়েছে। আমি বিশেষত যেটি ব্যবহার করছি তা হ'ল System.Web.Mvc.Html.RenderPartialExitionss.RenderPartial (এই এইচটিএমএল হেলপার, স্ট্রিং, অবজেক্ট)। এই পদ্ধতিটি এমভিসির সর্বশেষ সংশোধনীতে যুক্ত করা হয়েছে এবং আগের পদ্ধতিতে উপস্থিত ছিল না তা আমি অসচেতন।
LorenzCK

ধন্যবাদ। কেবলমাত্র সিস্টেম.ওয়েব.এমভিসি.এইচটিএমএল নামের স্থানটি ব্যবহারের ঘোষণায় যুক্ত করতে হবে (অন্যথায় এইচটিএমএল.রেন্ডার পার্টিশিয়াল (..) অবশ্যই অ্যাক্সেসযোগ্য হবে না :))
মার্টিনএফ

কেউ কি এমভিসি 2 এর আরসির সাথে এই কাজ করছে? তারা ভিউকন্টেক্সটে একটি অতিরিক্ত পাঠ্য লেখকের পরামিতি যুক্ত করেছে। আমি কেবল একটি নতুন স্ট্রিং রাইটার () যুক্ত করার চেষ্টা করেছি, তবে এটি কার্যকর হয়নি।
বেকেলমডব্লিউ

1
@ বেইকেলএমডাব্লু: আমি প্রতিক্রিয়া আপডেট করেছি। আপনি যে মূলটি StringWriterলিখতে ব্যবহার করছেন সেটিতে আপনাকে অবশ্যই পাস করতে হবে StringBuilder, কোনও নতুন উদাহরণ নয় বা ভিউটির আউটপুট নষ্ট হবে।
LorenzCK

11

এই নিবন্ধটি বর্ণনা করে যে কীভাবে বিভিন্ন পরিস্থিতিতে একটি স্ট্রিংয়ে একটি ভিউ রেন্ডার করতে হয়:

  1. এমভিসি কন্ট্রোলার নিজস্ব ক্রিয়াকলাপ থেকে অন্যকে কল করে
  2. MVC কন্ট্রোলার অন্য এমভিসি নিয়ামকের একটি অ্যাকশনমাথডকে কল করে
  3. ওয়েবপিআইআই কন্ট্রোলার একটি এমভিসি কন্ট্রোলারের একটি অ্যাকশনমাথডকে কল করে

দ্রবণ / কোডটি ভিউ রেন্ডারার নামে একটি শ্রেণি হিসাবে সরবরাহ করা হয় । এটি গিটহাবে রিক স্টাহলের ওয়েস্টউইন্ডটুলকিটের একটি অংশ ।

ব্যবহার (3. - ওয়েবএপিআই উদাহরণ):

string html = ViewRenderer.RenderView("~/Areas/ReportDetail/Views/ReportDetail/Index.cshtml", ReportVM.Create(id));

3
এছাড়াও নিউগেট প্যাকেজ ওয়েস্ট উইন্ড ওয়েব এমভিসি ইউটিলিটিস হিসাবে ( nuget.org/packages/Westwind.Web.Mvc )। বোনাস হিসাবে, ভিউ রেন্ডারার কেবল আংশিক দর্শনগুলিই সরবরাহ করতে পারে না, লেআউট সহ পুরো ভিউও সরবরাহ করতে পারে। কোড সহ ব্লগ নিবন্ধ: weblog.west-wind.com/posts/2012/ay/30/…
জেরোইন কে

এটি যদি ছোট প্যাকেজগুলিতে বিভক্ত হয় তবে দুর্দান্ত হবে। নুগেট প্যাকেজটি আপনার ওয়েব কোডফাইজে একগুচ্ছ পরিবর্তন করে এবং আপনার প্রকল্পে জেএস ফাইল যুক্ত করে, যা আপনি এটি আনইনস্টল করার পরে পরিষ্কার করা হয় না: /
জোশ নোই

8

আপনি যদি এমভিসি পুরোপুরি ত্যাগ করতে চান তবে এর মাধ্যমে সমস্ত এইচটিপিপি কনটেক্সট মেস এড়ানো ...

using RazorEngine;
using RazorEngine.Templating; // For extension methods.

string razorText = System.IO.File.ReadAllText(razorTemplateFileLocation);
string emailBody = Engine.Razor.RunCompile(razorText, "templateKey", typeof(Model), model);

এটি এখানে দুর্দান্ত অপার সোর্স রেজার ইঞ্জিন ব্যবহার করে: https://github.com/Antaris/RazorEngine


নিস! ওয়েব ফর্ম সিনট্যাক্সের জন্য একই রকম পার্সিং ইঞ্জিন রয়েছে কিনা তা কি আপনি জানেন? আমার এখনও কিছু পুরানো ওয়েব ফোরামের মতামত রয়েছে যা এখনও রেজারে সরানো যায় না।
ড্যান অ্যাটকিনসন

হাই, রেওরজাইন সম্পর্কে আমার অনেক সমস্যা ছিল, এবং ত্রুটি রিপোর্টিংটি খুব সুন্দর নয়। আমি মনে করি না যে ইউআরএল সহায়ক সমর্থিত
লেইঙ্কা

@ লায়ঙ্কা নিশ্চিত হয় না এটি সাহায্য করে কিনা তবে বেশিরভাগ ত্রুটির তথ্য CompilerErrorsব্যতিক্রমী সম্পত্তিটিতে রয়েছে।
জোশ

5

আপনি এভাবে স্ট্রিংয়ে ভিউ পাবেন

protected string RenderPartialViewToString(string viewName, object model)
{
    if (string.IsNullOrEmpty(viewName))
        viewName = ControllerContext.RouteData.GetRequiredString("action");

    if (model != null)
        ViewData.Model = model;

    using (StringWriter sw = new StringWriter())
    {
        ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
        ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
        viewResult.View.Render(viewContext, sw);

        return sw.GetStringBuilder().ToString();
    }
}

আমরা এই পদ্ধতিটিকে দুটি উপায়ে কল করছি

string strView = RenderPartialViewToString("~/Views/Shared/_Header.cshtml", null)

অথবা

var model = new Person()
string strView = RenderPartialViewToString("~/Views/Shared/_Header.cshtml", model)

4

এএসপি নেট কোরের জন্য অতিরিক্ত টিপ:

ইন্টারফেস:

public interface IViewRenderer
{
  Task<string> RenderAsync<TModel>(Controller controller, string name, TModel model);
}

বাস্তবায়ন:

public class ViewRenderer : IViewRenderer
{
  private readonly IRazorViewEngine viewEngine;

  public ViewRenderer(IRazorViewEngine viewEngine) => this.viewEngine = viewEngine;

  public async Task<string> RenderAsync<TModel>(Controller controller, string name, TModel model)
  {
    ViewEngineResult viewEngineResult = this.viewEngine.FindView(controller.ControllerContext, name, false);

    if (!viewEngineResult.Success)
    {
      throw new InvalidOperationException(string.Format("Could not find view: {0}", name));
    }

    IView view = viewEngineResult.View;
    controller.ViewData.Model = model;

    await using var writer = new StringWriter();
    var viewContext = new ViewContext(
       controller.ControllerContext,
       view,
       controller.ViewData,
       controller.TempData,
       writer,
       new HtmlHelperOptions());

       await view.RenderAsync(viewContext);

       return writer.ToString();
  }
}

নিবন্ধন Startup.cs

...
 services.AddSingleton<IViewRenderer, ViewRenderer>();
...

এবং নিয়ামক ব্যবহার:

public MyController: Controller
{
  private readonly IViewRenderer renderer;
  public MyController(IViewRendere renderer) => this.renderer = renderer;
  public async Task<IActionResult> MyViewTest
  {
    var view = await this.renderer.RenderAsync(this, "MyView", model);
    return new OkObjectResult(view);
  }
}

3

আমি এমভিসি 1.0 আরটিএম ব্যবহার করছি এবং উপরের সমাধানগুলির কোনওটিই আমার পক্ষে কার্যকর হয়নি। তবে এইটি করেছে:

Public Function RenderView(ByVal viewContext As ViewContext) As String

    Dim html As String = ""

    Dim response As HttpResponse = HttpContext.Current.Response

    Using tempWriter As New System.IO.StringWriter()

        Dim privateMethod As MethodInfo = response.GetType().GetMethod("SwitchWriter", BindingFlags.NonPublic Or BindingFlags.Instance)

        Dim currentWriter As Object = privateMethod.Invoke(response, BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.InvokeMethod, Nothing, New Object() {tempWriter}, Nothing)

        Try
            viewContext.View.Render(viewContext, Nothing)
            html = tempWriter.ToString()
        Finally
            privateMethod.Invoke(response, BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.InvokeMethod, Nothing, New Object() {currentWriter}, Nothing)
        End Try

    End Using

    Return html

End Function

2

আমি অন্য ওয়েবসাইট থেকে এমভিসি 3 এবং রেজারের জন্য একটি বাস্তবায়ন দেখেছি, এটি আমার পক্ষে কাজ করেছে:

    public static string RazorRender(Controller context, string DefaultAction)
    {
        string Cache = string.Empty;
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        System.IO.TextWriter tw = new System.IO.StringWriter(sb); 

        RazorView view_ = new RazorView(context.ControllerContext, DefaultAction, null, false, null);
        view_.Render(new ViewContext(context.ControllerContext, view_, new ViewDataDictionary(), new TempDataDictionary(), tw), tw);

        Cache = sb.ToString(); 

        return Cache;

    } 

    public static string RenderRazorViewToString(string viewName, object model)
    {

        ViewData.Model = model;
        using (var sw = new StringWriter())
        {
            var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
            var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
            viewResult.View.Render(viewContext, sw);
            return sw.GetStringBuilder().ToString();
        }
    } 

    public static class HtmlHelperExtensions
    {
        public static string RenderPartialToString(ControllerContext context, string partialViewName, ViewDataDictionary viewData, TempDataDictionary tempData)
        {
            ViewEngineResult result = ViewEngines.Engines.FindPartialView(context, partialViewName);

            if (result.View != null)
            {
                StringBuilder sb = new StringBuilder();
                using (StringWriter sw = new StringWriter(sb))
                {
                    using (HtmlTextWriter output = new HtmlTextWriter(sw))
                    {
                        ViewContext viewContext = new ViewContext(context, result.View, viewData, tempData, output);
                        result.View.Render(viewContext, output);
                    }
                }
                return sb.ToString();
            } 

            return String.Empty;

        }

    }

রেজার সম্পর্কিত আরও কিছু - এমভিসি 3 দেখুন স্ট্রিংয়ের স্ট্রিং


হ্যাঁ, এটি আসলে স্বীকৃত উত্তরের একটি অনুলিপি। :)
ড্যান অ্যাটকিনসন

2

চারদিকে কন্ট্রোলার কনটেক্সট পাস না করেই সার্ভিস লেয়ারে একটি স্ট্রিংয়ের একটি ভিউ রেন্ডার করতে, এখানে একটি ভাল রিক স্ট্রহল নিবন্ধ রয়েছে http://www.codemag.com/Article/1312081 যা জেনেরিক নিয়ামক তৈরি করে। নীচের কোড সংক্ষিপ্তসার:

// Some Static Class
public static string RenderViewToString(ControllerContext context, string viewPath, object model = null, bool partial = false)
{
    // first find the ViewEngine for this view
    ViewEngineResult viewEngineResult = null;
    if (partial)
        viewEngineResult = ViewEngines.Engines.FindPartialView(context, viewPath);
    else
        viewEngineResult = ViewEngines.Engines.FindView(context, viewPath, null);

    if (viewEngineResult == null)
        throw new FileNotFoundException("View cannot be found.");

    // get the view and attach the model to view data
    var view = viewEngineResult.View;
    context.Controller.ViewData.Model = model;

    string result = null;

    using (var sw = new StringWriter())
    {
        var ctx = new ViewContext(context, view, context.Controller.ViewData, context.Controller.TempData, sw);
        view.Render(ctx, sw);
        result = sw.ToString();
    }

    return result;
}

// In the Service Class
public class GenericController : Controller
{ }

public static T CreateController<T>(RouteData routeData = null) where T : Controller, new()
{
    // create a disconnected controller instance
    T controller = new T();

    // get context wrapper from HttpContext if available
    HttpContextBase wrapper;
    if (System.Web.HttpContext.Current != null)
        wrapper = new HttpContextWrapper(System.Web.HttpContext.Current);
    else
        throw new InvalidOperationException("Cannot create Controller Context if no active HttpContext instance is available.");

    if (routeData == null)
        routeData = new RouteData();

    // add the controller routing if not existing
    if (!routeData.Values.ContainsKey("controller") &&
        !routeData.Values.ContainsKey("Controller"))
        routeData.Values.Add("controller", controller.GetType().Name.ToLower().Replace("controller", ""));

    controller.ControllerContext = new ControllerContext(wrapper, routeData, controller);
    return controller;
}

তারপরে পরিষেবা শ্রেণিতে ভিউ রেন্ডার করতে:

var stringView = RenderViewToString(CreateController<GenericController>().ControllerContext, "~/Path/To/View/Location/_viewName.cshtml", theViewModel, true);

1

দ্রুত নির্দেশনা

দৃ strongly়ভাবে টাইপ করা মডেলের জন্য রেন্ডারভিউটোস্ট্রিংয়ে যাওয়ার আগে এটিকে ভিউডাটা.মডেল বৈশিষ্ট্যে যুক্ত করুন। যেমন

this.ViewData.Model = new OrderResultEmailViewModel(order);
string myString = RenderViewToString(this.ControllerContext, "~/Views/Order/OrderResultEmail.aspx", "~/Views/Shared/Site.Master", this.ViewData, this.TempData);

0

আরও অজানা প্রশ্ন থেকে পুনরাবৃত্তি করতে, এমভিসিআইন্টিগ্রেশন টেস্টফ্রেমওয়ার্কটি একবার দেখুন

এটি ফলাফলকে স্ট্রিম করতে আপনার নিজের সহায়তাকারীদের লেখার সাশ্রয় করে এবং যথেষ্ট পরিমাণে কাজ করার পক্ষে প্রমাণিত। আমি ধরে নিই এটি একটি পরীক্ষামূলক প্রকল্পে হবে এবং বোনাস হিসাবে আপনি যখন এই সেটআপটি পেয়েছেন তখন অন্যান্য পরীক্ষার ক্ষমতাও আপনার হবে। মূল উদ্বেগ সম্ভবত নির্ভরতা শৃঙ্খলা বাছাই করা হবে।

 private static readonly string mvcAppPath = 
     Path.GetFullPath(AppDomain.CurrentDomain.BaseDirectory 
     + "\\..\\..\\..\\MyMvcApplication");
 private readonly AppHost appHost = new AppHost(mvcAppPath);

    [Test]
    public void Root_Url_Renders_Index_View()
    {
        appHost.SimulateBrowsingSession(browsingSession => {
            RequestResult result = browsingSession.ProcessRequest("");
            Assert.IsTrue(result.ResponseText.Contains("<!DOCTYPE html"));
        });
}

0

এটিএসপি.নাইটকোর আরসি 2 এর জন্য এটি করার জন্য আমি এখানে একটি ক্লাস লিখেছি। আমি এটি ব্যবহার করি যাতে আমি রেজার ব্যবহার করে এইচটিএমএল ইমেল তৈরি করতে পারি।

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Routing;
using System.IO;
using System.Threading.Tasks;

namespace cloudscribe.Web.Common.Razor
{
    /// <summary>
    /// the goal of this class is to provide an easy way to produce an html string using 
    /// Razor templates and models, for use in generating html email.
    /// </summary>
    public class ViewRenderer
    {
        public ViewRenderer(
            ICompositeViewEngine viewEngine,
            ITempDataProvider tempDataProvider,
            IHttpContextAccessor contextAccesor)
        {
            this.viewEngine = viewEngine;
            this.tempDataProvider = tempDataProvider;
            this.contextAccesor = contextAccesor;
        }

        private ICompositeViewEngine viewEngine;
        private ITempDataProvider tempDataProvider;
        private IHttpContextAccessor contextAccesor;

        public async Task<string> RenderViewAsString<TModel>(string viewName, TModel model)
        {

            var viewData = new ViewDataDictionary<TModel>(
                        metadataProvider: new EmptyModelMetadataProvider(),
                        modelState: new ModelStateDictionary())
            {
                Model = model
            };

            var actionContext = new ActionContext(contextAccesor.HttpContext, new RouteData(), new ActionDescriptor());
            var tempData = new TempDataDictionary(contextAccesor.HttpContext, tempDataProvider);

            using (StringWriter output = new StringWriter())
            {

                ViewEngineResult viewResult = viewEngine.FindView(actionContext, viewName, true);

                ViewContext viewContext = new ViewContext(
                    actionContext,
                    viewResult.View,
                    viewData,
                    tempData,
                    output,
                    new HtmlHelperOptions()
                );

                await viewResult.View.RenderAsync(viewContext);

                return output.GetStringBuilder().ToString();
            }
        }
    }
}

0

উপরের পদ্ধতিগুলির সাথে ত্রুটি পেয়ে আমি রেজার ভিউ পৃষ্ঠাটি রেন্ডার করার একটি আরও ভাল উপায় খুঁজে পেয়েছি, ওয়েব ফর্ম পরিবেশ এবং এমভিসি পরিবেশ উভয়ের জন্য এই সমাধান। কোনও নিয়ামকের প্রয়োজন হয় না।

কোডের উদাহরণটি এখানে দেওয়া আছে, উদাহরণস্বরূপ আমি একটি এসভিএনপি হ্যান্ডলারের সাহায্যে একটি এমভিসি ক্রিয়া অনুকরণ করেছি:

    /// <summary>
    /// Enables processing of HTTP Web requests asynchronously by a custom HttpHandler that implements the IHttpHandler interface.
    /// </summary>
    /// <param name="context">An HttpContext object that provides references to the intrinsic server objects.</param>
    /// <returns>The task to complete the http request.</returns>
    protected override async Task ProcessRequestAsync(HttpContext context)
    {
        if (this._view == null)
        {
            this.OnError(context, new FileNotFoundException("Can not find the mvc view file.".Localize()));
            return;
        }
        object model = await this.LoadModelAsync(context);
        WebPageBase page = WebPageBase.CreateInstanceFromVirtualPath(this._view.VirtualPath);
        using (StringWriter sw = new StringWriter())
        {
            page.ExecutePageHierarchy(new WebPageContext(new HttpContextWrapper(context), page, model), sw);
            await context.Response.Output.WriteAsync(sw.GetStringBuilder().ToString());
        }
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.