Render string as MVC View - asp.net-mvc

I have a simple Email Composer class where I get all Application Emails content from.
In this example, it sends the products to the email.
Now, I want to print them as well, and I'm trying to re-use the same method to grab the full html from the Email Composer and output it to a View.
the controller action
public ActionResult PrintRules()
{
var products = rep.ListAllProductsByCompanyId(currentCompany.company_id);
string body = mail.GetProductRules(products);
ViewBag.email = HttpUtility.HtmlEncode(body);
return View();
}
the view is:
#{
Layout = null;
string email = HttpUtility.HtmlDecode(ViewBag.email);
}
#Html.Raw(email)
<script>
window.print();
</script>
If I pass the body as a Model I do get errors on the parser, so I'm using the ViewBag instead.
as outputs:
#Html.Raw(email) will output nothing at all
#Html.Raw(email.Length) will output 17463
#email will output the code but the browser outputs it, does not parse it (image below)
What am I missing? I know it must be a really simple thing, but I'm totally blank...
browser output from using #email

Try this
#(new HtmlString(mystring))
or
#MvcHtmlString.Create(ViewBag.Stuff)

Related

Display image from byte array in ASP.NET MVC Core

I have a byte[] stored in a VARBINARY(MAX) column in a table in my database.
I want to show this image on my index.cshtml page - but I'm stuck.
My CSHTML looks like this:
#using Microsoft.AspNetCore.Hosting.Internal
#{
ViewData["Title"] = "Title";
}
<h2>#ViewData["Title"]</h2>
<h3>#ViewData["Message"]</h3>
#if (!Context.User.Identity.IsAuthenticated)
{
<p>blah blah.</p>
<p>blah blah</p>
}
#if (Context.User.Identity.IsAuthenticated)
{
<p>Hi #(Context.User.Identity.Name)<br/></p>
<p>Where we off to today?</p>
}
I want to add
<img src="...." />
obviously I don't know what to do here.
My model has the byte array data:
public byte[] UserImage { get; set; }
My controller assigned that the value:
var model = new IndexViewModel
{
Username = user.UserName,
Email = user.Email,
PhoneNumber = user.PhoneNumber,
IsEmailConfirmed = user.EmailConfirmed,
StatusMessage = StatusMessage,
UserImage = user.UserImage
};
but I am using .net core in VS2017 and the answers I have found don't seem to work for me. Any help would be really appreciated.
Thanks
Johan
You have two options:
Base64 encode the byte[] and use a Data URI:
<img src="data:image/png;base64,[base64-encoded byte array here]">
However, bear in mind two things. 1) Data URIs are supported in every modern browser, but notoriously do not work in IE 10 and under. That may not be an issue, but if you need to have legacy IE support, this is a non-starter. 2) Since you're Base64-encoding, the size of the "image" will balloon roughly 50%. As such, Data URIs are best used with small and simple images. If you've got large images or simply a lot of images, your HTML document can become a very large download. Since Data URIs are actually embedded in the HTML code, that means the browser cannot actually begin to render the page at all until the entire HTML document has loaded, which then also means that if it's megabytes in size, your users will be waiting a while.
Create an action that pulls the image from the database and returns it as a FileResult. This is the most optimal path. Essentially, you just need an action that accepts some sort of identifier for the image, which can be used to pull it from the database. You then return the byte[] like:
return File(myByteArray, "image/png");
In your view, you simply make the image source the route to this action:
<img src="#Url.Action("GetImage", "Foo", new { id = myImageIdentifier }">
Ok so I managed to work it out with the help above. I created a method on the controller that looks like this:
public FileResult GetFileFromBytes(byte[] bytesIn)
{
return File(bytesIn, "image/png");
}
[HttpGet]
public async Task<IActionResult> GetUserImageFile()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return null;
}
FileResult imageUserFile = GetFileFromBytes(user.UserImage);
return imageUserFile;
}
in my cshtml I then added this:
<img src= '#Url.Action("GetUserImageFile", "Manage")'/>
"Manage" was the start of the controller name. I didnt need to pass in an ID as my image bytes are stored on the aspuser so the code knows which user it is using the GetUserAsync
Can anyone see problems with this? Also, it doesnt seem to care that the origional image is a jpeg but in the code I am using "image/png", am I risking losing something?
Many thanks for the comments and help! this is such an amazing forum!

Changes to VM after POST not reflected in the Page [duplicate]

I want to send a message to userID=3 by going to /MyController/Message/3
This executes Message() [get] action, I enter some text in the text area and click on Save to post the form
Message() [post] action saves the changes, resets the value of SomeText to empty string and returns to the view.
At this point I expect the text area to be empty because I have set ViewData["SomeText"] to string.Empty.
Why is text area value not updated to empty string after post action?
Here are the actions:
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Message(int ID)
{
ViewData["ID"] = ID;
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Message(int ID, string SomeText)
{
// save Text to database
SaveToDB(ID, SomeText);
// set the value of SomeText to empty and return to view
ViewData["SomeText"] = string.Empty;
return View();
}
And the corresponding view:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<% using (Html.BeginForm())
{ %>
<%= Html.Hidden("ID", ViewData["ID"])%>
<label for="SomeText">SomeText:</label>
<%= Html.TextArea("SomeText", ViewData["SomeText"]) %>
<input type="submit" value="Save" />
<% } %>
</asp:Content>
The problem is that your ModelState is re-filled with the posted values.
What you can do is clear it on the Action that has the Post attribute :
ModelState.Clear();
The problem is the HtmlHelper is retrieving the ModelState value, which is filled with the posted data. Rather than hacking round this by resetting the ModelState, why not redirect back to the [get] action. The [post] action could also set a temporary status message like this:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Message(int ID, string SomeText)
{
// save Text to database
SaveToDB(ID, SomeText);
TempData["message"] = "Message sent";
return RedirectToAction("Message");
}
This seems to me like more correct behaviour.
The html helpers read the value from the ModelState. And there's no elegant way to override this behaviour.
But if you add this line after SaveToDB(ID, SomeText), it should work :
ModelState["SomeText"].Value =
new ValueProviderResult("", "", CultureInfo.CurrentCulture);
I tried everything, but only worked when I did something like this:
ModelState.Clear();
//This will clear the address that was submited
viewModel.Address = new Address();
viewModel.Message = "Dados salvos com sucesso!";
return View("Addresses", ReturnViewModel(viewModel));
Hope this helps.
Instead of using ModelState.Clear() which clears the whole modelstate, you can do ModelState.Remove("SomeText"), if you want to. Or render the Input without the htmlhelper-extensions.
They are designed to take the Value from ModelState instead of the Model (or viewdata).
That is a clientside behavior. I would recommend using javascript. If you use JQuery, you can do it like this:
<script type="text/javascript">
$(function(){ $("#SomeText").val("");});
</script>
I don't use Javascript anymore, but I believe in regular JS that it is like:
document.getElementById("SomeText").value = "";
(You would do this on one of the load events.
<body onload="...">
Hope this helps.
I am fairly certain the textarea is grabbing the value from the Request.Form under the hood since ViewData["SomeText"] is empty.
Is it possible that the model state has been updated with an error? I believe that it will pull the attempted value from the model state rather than from view data or the model if the model state isn't valid.
EDIT:
I'm including the relevant section of the source code from the TextArea HtmlHelper extension below. It appears to me that it does exactly what I expected -- if there has been a model error, it pulls the value from the model state, otherwise it uses it from ViewData. Note that in your Post method the "SomeText" key shouldn't even exist until you set it, i.e., it won't be carried forward from the version of the code that responds to the GET.
Since you explicitly supply a value to the ViewData, useViewData should be false, attemptedValue should be false unless an error has been set in the model state.
// If there are any errors for a named field, we add the css attribute.
ModelState modelState;
if (htmlHelper.ViewData.ModelState.TryGetValue(name, out modelState)) {
if (modelState.Errors.Count > 0) {
tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
}
}
// The first newline is always trimmed when a TextArea is rendered, so we add an extra one
// in case the value being rendered is something like "\r\nHello".
// The attempted value receives precedence over the explicitly supplied value parameter.
string attemptedValue = (string)htmlHelper.GetModelStateValue(name, typeof(string));
tagBuilder.SetInnerText(Environment.NewLine + (attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(name) : value)));
return tagBuilder.ToString(TagRenderMode.Normal);
Do s.th. like this:
add:
ModelState.Clear();
before the return statement of the submit buttons action method. Works for me. It could work for you.

asmx web service and MVC 3 - How to use Model and map web service data to it?

I have a web service and I want to display the data from web service in my MVC Razor View.
This is what I have done:
1) My Web Method:
[WebMethod]
public string HelloWorld()
{
return "Hello World... This is a Web Service consumed
through MVC Project";
}
2) Added web reference to my MVC Project
3) View :
<table><tr><td>
<input type="button" id="btnSubmit" value="Get Message"
onclick="javascript:getMessage();" />
</td></tr></table>
<div id="Result"></div>
4) Script in my view
function getMessage() {
var URL = "/Home/getMessage/";
$.get(URL, function (data) {
$("#Result").html(data);
});
}
Note : Controller name is Home and Action Method is getMessage
5) Action Method in Home
public string getMessage()
{
Service1 mvcServiceProxy = new Service1();
string message = mvcServiceProxy.HelloWorld();
return message;
}
I have followed the above steps and I am able to get the message in to my DIV as per my javascript code.
But If I have a model, and the property in my model is like: public string Message{ get; set; }
How can I get the message into this property? DO I need to modify my action method and Javascript? Should I use something like JSON ?
I am not sure of how to achive this...
I just want to use my property and display the content (message) from my web service into my Razor view using my model property instead of passing the html value into DIV and directly displaying it.
Please suggest.
Thanks in advance !!!!
First of all property is basically used to read/modify any private data in a class from another Type.
So what you are trying to achieve shouldn't be done with properties.
The way you are trying is ok, also you can get a complete list of data in one call using Json and set it on html page according to your need.
So I would recommend playing around with Json.

Sending Emails with ActionMailer.Mvc in VB, Cannot Find View

The error I get when I try to send an email is:
NoViewsFoundException
You must provide a view for this email. Views should be named
~/Views/Email/VerificationEmail.html.vbhtml.txt.cshtml or
~/Views/Email/VerificationEmail.html.vbhtml.html.cshtml (or aspx for
WebFormsViewEngine) depending on the format you wish to render.
Error on line:
Return Email("~/Views/Email/VerificationEmail.html.vbhtml", model)
Can emails not be sent in .vbhtml, must they be sent in .cshtml? How can this work for VB?
Here is my code controller:
Imports ActionMailer.Net.Mvc
Public Class EmailController
Inherits MailerBase
Public Function VerificationEmail(ByVal model As RegisterModel) As EmailResult
[To].Add(model.Email)
From = "me#my.org"
Subject = "Thanks for registering with us!"
Return Email("~/Views/Email/VerificationEmail.html.vbhtml", model)
End Function
End Class
Here is my view:
#modelType MyBlog.RegisterModel
#Code
Layout = Nothing
End code
Welcome to My Cool Site, #Model.UserName
We need you to verify your email. Click this nifty link to get verified!
#Html.ActionLink("Verify", "Account", New With {.code = Model.Email})
Thanks!
After reading a couple of issues and answer, it could get it to work with this:
public override string ViewPath {
get { return AppDomain.CurrentDomain.BaseDirectory + #"\EmailTemplates\"; }
}
Of course you can have vbhtml email templates you just need to be careful with the naming (the .cshtmls exception message are hardcoded so don't be confused on it)
Your view is named correctly as VerificationEmail.html.vbhtml you just need remove all the prefixes from the view name in the Email call:
Return Email("VerificationEmail", model)
Because ActionMailer will be automatically add the prefixes and select the correct template for you.
Note that currently you cannot use relative viewnames like which start with ~ e.g. "~/Views/..." (I don't know wether this is a bug or feature).
So you need put your mail template to the regular view folders e.g.
/Views/{MailControllerName}/
/View/Shared/
Had the same issue as Chad Richardson. To solve the issue which happens when trying to send email from other area just add this code to Application_Start method:
var razorEngine = ViewEngines.Engines.OfType<RazorViewEngine>().First();
razorEngine.ViewLocationFormats = razorEngine.ViewLocationFormats.Concat(new string[]
{
"~/Areas/.../{0}.cshtml"
}).ToArray();

Validation detected dangerous client input - post from TinyMCE in ASP.NET

I get this error when I post from TinyMCE in an ASP.NET MVC view.
Error:
Request Validation has detected a potentially dangerous client input value, and processing of the request has been aborted
From googling, it says to just add a validateRequest in the Page directive at the top which I did, but I STILL get this error. As you can see, below is my code in the view:
<%# Page validateRequest="false" Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
Try this solution. simply add to TinyMce control
tinyMCE.init({
...
encoding : "xml"
});
http://wiki.moxiecode.com/index.php/TinyMCE:Configuration/encoding
http://blog.tentaclesoftware.com/archive/2010/07/22/96.aspx
Try using the [AllowHtml] attribute in your model.
class MyModel{
[AllowHtml]
public string Content{get;set;}
}
Use the decorator [ValidateInput(false)].
You will then want to write a HTMLEncode method to make it safe.
Let me know if you want me to post the one I use.
Added the Encode I use
public static class StringHelpers
{
public static string HtmlEncode(this string value)
{
if (!string.IsNullOrEmpty(value))
{
value = value.Replace("<", "<");
value = value.Replace(">", ">");
value = value.Replace("'", "&apos;");
value = value.Replace(#"""", """);
}
return value;
}
public static string HtmlDecode(this string value)
{
if (!string.IsNullOrEmpty(value))
{
value = value.Replace("<", "<");
value = value.Replace(">", ">");
value = value.Replace("&apos;", "'");
value = value.Replace(""", #"""");
}
return value;
}
}
Annoyingly in version 4 of tinymce they seem to have removed the encoding: xml option.
I ended up using a javascript HTML encoding function from this answer, and on my submit button I encode the contents of the textarea before the form submits, by using tinymce's getContent and setContent methods
I had the same problem. I didn't want to disable ASP.NET MVC validation feature, so I kept looking until I reached this solution:
At the tinyMCE plugin code encode your content (I'm using the older version)
tinyMCE.init({
...
encoding: "xml"
});
And after this I didn't get any more the application validation error. Then I came up with another problem when I edited my form the code would come up with the html tags
<strong>My input value</strong>
instead of this
My input value
So, I had to decode the html for that field when getting my values at the Controller, like this:
...
entity.field = HttpUtility.HtmlDecode(entity.field);

Resources