I'm a beginner in ASP.net MVC and I have a problem when I want to send my view by email with my controller.
I do not arrive to send it, I just arrive send some text
About what I have already tried, I'm gonna show you with the code.
(If my problem is not understandable tel me and I explain differently)
// Page MailHelper.cs
// The tools for sending mail
public static void SendMail(string body)
{
try
{
var mailto = ConfigurationManager.AppSettings["mailto"].Split(';');
MailMessage mail = new MailMessage();
mail.IsBodyHtml = true;
SmtpClient SmtpServer = new SmtpClient();
mail.From = new MailAddress("SendVersionsRobot#trysomething.fr");
foreach (var m in mailto)
mail.To.Add(m);
mail.Subject = "try send Mail";
mail.Body = body;
SmtpServer.Send(mail);
}
catch (Exception ex)
{
}
}
// Page MailController.cs
using....
namespace MvcMovie.Controllers
{
public class MailController : Controller
{
public ActionResult pageDeTest()
{
MailHelper.SendMail(pageDeTest());
return View();
}
}
}
<div id="demo"></div>
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script type="text/javascript">
$.getJSON("..\\..\\jsconfig.json", function (data) {
$('#demo').html(JSON.stringify(data));
});
/*console.log("try");*/
</script>
Currently my page MailController.cs had evolve like that:
namespace MvcMovie.Controllers
{
public class MailController : Controller
{
public ActionResult pageDeTest()
{
string myString = RenderPartialViewToString(MailHelper.SendMail());
MailHelper.SendMail(myString);
return View();
}
protected string RenderPartialViewToString(ControllerContext context, string viewName, object model)
{
var controller = context.Controller;
if (string.IsNullOrEmpty(viewName))
viewName = controller.ControllerContext.RouteData.GetRequiredString("action");
ViewData.Model = model;
using (StringWriter sw = new StringWriter())
{
ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
ViewContext viewContext = new ViewContext(controller.ControllerContext, viewResult.View, ViewData, TempData, sw);
viewResult.View.Render(viewContext, sw);
return sw.GetStringBuilder().ToString();
}
}
Following is my Action
public PartialViewResult PrintOrder(string orderNo)
{
ViewBag.OrderId = orderNo;
return PartialView();
}
Following is my code
public static String RenderViewToString(PartialViewResult result,ControllerContext context, String viewPath,string orderNo, object model = null)
{
context.Controller.ViewData.Model = model;
using (var sw = new StringWriter())
{
result.View = ViewEngines.Engines.FindPartialView(context, "PrintOrder").View;
ViewContext vc = new ViewContext(context, result.View, result.ViewData, result.TempData, sw);
result.View.Render(vc, sw);
var html = sw.GetStringBuilder().ToString();
return html;
}
//return "No Data";
}
I am getting an error at result.View.Render(vc, sw) as "Value does not fall within the expected range."
what is the error ?
If required to convert your partial view to html string and return the string from the controller try this code.
Public ActionResult PrintOrder(string orderNo)
{
//code to get the model
this.ViewData.Model = YourModel;
//ViewData["ordno"] = orderNo; uncomment this if you need
var htmlStr = string.Empty;
try {
var sw = new StringWriter();
var viewResult = ViewEngines.Engines.FindPartialView(this.ControllerContext, "partialviewName");
var viewContext = new ViewContext(this.ControllerContext, viewResult.View, this.ViewData, this.TempData, sw);
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
htmlStr = sw.GetStringBuilder().ToString();
}catch(Exception e){
}
return htmlStr;
}
on a button click I want to pass value to Action method of type HttpGet and then display it on cshtml
Ex:Controller method
[HttpGet]
public ActionResult GetMandateListForCustomer(int userId, int customerId)
{
var receiptBankUserList = new CustomerMandateReport()
{
GetMandateListForCustomer = _mandateManager.GetMandateListForCustomer(userId, customerId)
};
return View(receiptBankUserList);
}
Here is some example how to do this:
Controller:
[HttpGet]
public string GetMandateListForCustomer(int userId, int customerId)
{
var receiptBankUserList = new CustomerMandateReport()
{
GetMandateListForCustomer = _mandateManager.GetMandateListForCustomer(userId, customerId)
};
return RenderRazorViewToString("ViewName", receiptBankUserList);
}
// use this method to change your view into string
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();
}
}
}
Method to render view as string is from here
Javascript
$('#btnAddElement').click(function () {
$.get("UrlToAction?userIDd=123&customerId=321", function (data) {
// replace element with class result with
// our new html which we get from controller
$(".result").html(data);
});
});
Code in javascript
function SubmitQuery(Org_UID) {
var ddlProduct_No = $("#Org_UID");
$.ajax({
type: 'POST',
url: '#Url.Action("ShowNewProfessionalWindow", "UpdateOrganizationUID")',
dataType: "html",
data: {
countryno: $("#Org_UID").val() }
My Controller
[HttpPost]
public ActionResult ShowNewProfessionalWindow(string countryno)
{
UpdateOrganizationUIDViewModel model = new UpdateOrganizationUIDViewModel();
//model.Org_UID = OrgUID;
model.org_name_long = "test";
model.org_name_short = "test";
return RedirectToAction("Index", model);
}
How can I return value of model to view using jquery?
Use JsonResult
Change your code and return JsonResult, So use
return Json(model);
instead of
return RedirectToAction("Index", model);
If you want to return View use
First you can create a method as, which will accept ViewName and Model it will return HTML string
public static string RenderRazorViewToString(ControllerContext controllerContext, string viewName, object model)
{
controllerContext.Controller.ViewData.Model = model;
using (var sw = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindPartialView(controllerContext, viewName);
var viewContext = new ViewContext(controllerContext, viewResult.View,
controllerContext.Controller.ViewData, controllerContext.Controller.TempData, sw);
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(controllerContext, viewResult.View);
return sw.GetStringBuilder().ToString();
}
}
Usage also you have to return JsonResult instead of PartialViewResult
public JsonResult yourpartialviewresult()
{
return Json(new
{
data = RenderRazorViewToString(this.ControllerContext, "partialview", model)
});
}
I have the following code:
public ActionResult SomeAction()
{
return new JsonpResult
{
Data = new { Widget = "some partial html for the widget" }
};
}
I'd like to modify it so that I could have
public ActionResult SomeAction()
{
// will render HTML that I can pass to the JSONP result to return.
var partial = RenderPartial(viewModel);
return new JsonpResult
{
Data = new { Widget = partial }
};
}
is this possible? Could somebody explain how?
note, I edited the question before posting the solution.
I opted for an extension method like the following for an ASP.NET MVC 4 app. I think it's simpler than some of the suggestions I've seen:
public static class ViewExtensions
{
public static string RenderToString(this PartialViewResult partialView)
{
var httpContext = HttpContext.Current;
if (httpContext == null)
{
throw new NotSupportedException("An HTTP context is required to render the partial view to a string");
}
var controllerName = httpContext.Request.RequestContext.RouteData.Values["controller"].ToString();
var controller = (ControllerBase)ControllerBuilder.Current.GetControllerFactory().CreateController(httpContext.Request.RequestContext, controllerName);
var controllerContext = new ControllerContext(httpContext.Request.RequestContext, controller);
var view = ViewEngines.Engines.FindPartialView(controllerContext, partialView.ViewName).View;
var sb = new StringBuilder();
using (var sw = new StringWriter(sb))
{
using (var tw = new HtmlTextWriter(sw))
{
view.Render(new ViewContext(controllerContext, view, partialView.ViewData, partialView.TempData, tw), tw);
}
}
return sb.ToString();
}
}
It allows me to do the following:
var html = PartialView("SomeView").RenderToString();
Also, this approach persists any Model, ViewBag and other view data for the view.
This is a slightly modified version of an answer that works:
public static string RenderPartialToString(string controlName, object viewData)
{
ViewPage viewPage = new ViewPage() { ViewContext = new ViewContext() };
viewPage.ViewData = new ViewDataDictionary(viewData);
viewPage.Controls.Add(viewPage.LoadControl(controlName));
StringBuilder sb = new StringBuilder();
using (StringWriter sw = new StringWriter(sb))
{
using (HtmlTextWriter tw = new HtmlTextWriter(sw))
{
viewPage.RenderControl(tw);
}
}
return sb.ToString();
}
Usage:
string ret = RenderPartialToString("~/Views/MyController/MyPartial.ascx", model);
DaveDev's answer worked well for me, however when the partial view calls another partial I get "Value cannot be null. Parameter name: view"
Searching around I have made a variant of the following that seems to work well.
public static string RenderPartialToString(string viewName, object model, ControllerContext ControllerContext)
{
if (string.IsNullOrEmpty(viewName))
viewName = ControllerContext.RouteData.GetRequiredString("action");
ViewDataDictionary ViewData = new ViewDataDictionary();
TempDataDictionary TempData = new TempDataDictionary();
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();
}
}
Usage:
String result = MVCHelpers.RenderPartialToString("PartialViewHere", Model, ControllerContext)
You can create extension that render view into string.
public static class RenderPartialToStringExtensions
{
/// <summary>
/// render PartialView and return string
/// </summary>
/// <param name="context"></param>
/// <param name="partialViewName"></param>
/// <param name="model"></param>
/// <returns></returns>
public static string RenderPartialToString(this ControllerContext context, string partialViewName, object model)
{
return RenderPartialToStringMethod(context, partialViewName, model);
}
/// <summary>
/// render PartialView and return string
/// </summary>
/// <param name="context"></param>
/// <param name="partialViewName"></param>
/// <param name="viewData"></param>
/// <param name="tempData"></param>
/// <returns></returns>
public static string RenderPartialToString(ControllerContext context, string partialViewName, ViewDataDictionary viewData, TempDataDictionary tempData)
{
return RenderPartialToStringMethod(context, partialViewName, viewData, tempData);
}
public static string RenderPartialToStringMethod(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;
}
public static string RenderPartialToStringMethod(ControllerContext context, string partialViewName, object model)
{
ViewDataDictionary viewData = new ViewDataDictionary(model);
TempDataDictionary tempData = new TempDataDictionary();
return RenderPartialToStringMethod(context, partialViewName, viewData, tempData);
}
}
And then use it in action
[HttpPost]
public ActionResult GetTreeUnit(string id)
{
int _id = id.ExtractID();
string render = ControllerContext.RenderPartialToString("SomeView");
return Json(new { data = render });
}
Works perfect (Only view name required)
* for parameters you can use a model
* can call this from a view also
View side or Calling Side
BuyOnlineCartMaster ToInvoice1 = new BuyOnlineCartMaster(); // for passing parameters
ToInvoice1.CartID = 1;
string HtmlString = RenderPartialViewToString("PartialInvoiceCustomer", ToInvoice1);
Function Generating HTML
public class BuyOnlineCartMaster
{
public int CartID { get; set; }
}
public static string RenderPartialViewToString(string viewName, object model)
{
using (var sw = new StringWriter())
{
BuyOnlineController controller = new BuyOnlineController(); // instance of the required controller (you can pass this as a argument if needed)
// Create an MVC Controller Context
var wrapper = new HttpContextWrapper(System.Web.HttpContext.Current);
RouteData routeData = new RouteData();
routeData.Values.Add("controller", controller.GetType().Name
.ToLower()
.Replace("controller", ""));
controller.ControllerContext = new ControllerContext(wrapper, routeData, controller);
controller.ViewData.Model = model;
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);
return sw.ToString();
}
}
Partial View page
#{
var ModelContents = (Common.BuyOnlineCartMaster)ViewData.Model;
}
Your cart id : #(ModelContents.CartID)
Dave,
a variation on the same theme (mvc v1.0):
protected static string RenderPartialToString(Controller controller, string partialName, object model)
{
var vd = new ViewDataDictionary(controller.ViewData);
var vp = new ViewPage
{
ViewData = vd,
ViewContext = new ViewContext(),
Url = new UrlHelper(controller.ControllerContext.RequestContext)
};
ViewEngineResult result = ViewEngines
.Engines
.FindPartialView(controller.ControllerContext, partialName);
if (result.View == null)
{
throw new InvalidOperationException(
string.Format("The partial view '{0}' could not be found", partialName));
}
var partialPath = ((WebFormView)result.View).ViewPath;
vp.ViewData.Model = model;
Control control = vp.LoadControl(partialPath);
vp.Controls.Add(control);
var sb = new StringBuilder();
using (var sw = new StringWriter(sb))
{
using (var tw = new HtmlTextWriter(sw))
{
vp.RenderControl(tw);
}
}
return sb.ToString();
}
usage within controller:
public string GetLocationHighlites()
{
IBlockData model = WebPagesMapper.GetLocationHighlites();
// **this** being the controoler instance
// LocationPartial.ascx can be defined in shared or in view folder
return RenderPartialToString(**this**,"LocationPartial", model);
}
You can do that out of the box with:
var partial = new HtmlString(Html.Partial("_myPartial", Model).ToString());
public virtual string RenderPartialViewToString(string viewName, object viewmodel)
{
if (string.IsNullOrEmpty(viewName))
{
viewName = this.ControllerContext.RouteData.GetRequiredString("action");
}
ViewData.Model = viewmodel;
using (var sw = new StringWriter())
{
ViewEngineResult viewResult = System.Web.Mvc.ViewEngines.Engines.FindPartialView(this.ControllerContext, viewName);
var viewContext = new ViewContext(this.ControllerContext, viewResult.View, this.ViewData, this.TempData, sw);
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
return sw.GetStringBuilder().ToString();
}
}
Old post, but I think you are making this too difficult.
Why not return PartialView("<my partial>", model); will return the string you desire.
Just make the Get/Post method an IActionResult as JsonResult, PartialResultand other inherit from ActionResult you can send back anything including a JsonResult
[HttpPost]
public IActionResult CheckForContent(string id, string type){
try{
if(type = "something"){
return Json(new {
success = true,
myProp = "this prop"
});
} else {
MyViewModel model = new MyViewModel();
model.Content = _service.GetContent(new GetContentRequest(){ id = id }
return PartialView("<my partial>", model);
} catch(Exception ex){
_logger.LogError(ex.Message);
return Json(new { success = false }
}
}
Ajax:
$.ajax({
url: '/CheckForContent',
type: 'POST',
cache: false,
contentType: false,
processData: false,
success: function (result) {
if(!result && !result.success){
console.log("Failed to load");
} else if(result && result.success){
$('#MyProp').val(result.myProp);
} else {
$('#MyContainer').html(result);
}
},
});