What is the equivalent to Page.ResolveUrl in ASP.NET MVC? - asp.net-mvc

What is the equivalent to Page.ResolveUrl in ASP.NET MVC available in the Controller?

It is Url.Content:
ASPX:
<link rel="stylesheet" href="<%= Url.Content("~/Content/style.css") %>" type="text/css" />
Razor:
<link rel="stylesheet" href="#Url.Content("~/Content/style.css")" type="text/css" />

This should do what you're looking for...
System.Web.VirtualPathUtility.ToAbsolute("~/")

Here are a whole bunch of ways to resolve a path that uses that application root operator (~)
UrlHelper.Content
HttpServerUtility.MapPath
WebPageExecutingBase.Href
VirtualPathUtility.ToAbsolute
Control.ResolveUrl
To call any method with inline code on an asp.net page, the method either needs to be exposed as an instance variable on the current object, or available as a static/shared method.
A typical MVC page gives us access to quite a few of these as properties via the WebViewPage. Ever wonder when you type #ViewData, you get magically wired up to the ViewData? That's because you have hit a property exposed by the MVC page you're on.
So to call these methods, we don't necessarily refer to the type they represent, but the instance property that exposes them.
We can call the above instance methods like this (respectively):
href="#Url.Content("~/index.html")"
href="#Server.MapPath("~/index.html")"
href="#Href("~/index.html")"
We can do this to call a shared method that doesn't need an instance:
href="#VirtualPathUtility.ToAbsolute("~/index.html")"
AFAIK, an MVC page doesn't automatically create an instance of anything from the System.Web.UI namespace, from which ResolveUrl inherits. If, for some reason, you really wanted to use that particular method, you could just new up a control and use the methods it exposes, but I would highly recommend against it.
#Code
Dim newControl As New System.Web.UI.Control
Dim resolvedUrl = newControl.ResolveUrl("~/index.html")
End Code
href="#resolvedUrl"
That all said, I would recommend using #Url.Content as it fits best with MVC paradigms

UrlHelper.Content() does the same thing as Control.ResolveUrl().
For Further References:
http://stephenwalther.com/archive/2009/02/18/asp-net-mvc-tip-47-ndash-using-resolveurl-in-an-html.aspx

You don't need to do this anymore in Razor v2.0/ASP.NET MVC 4.
Just use the "~" in a razor page and it will resolve it for you.
<link rel="stylesheet" href="~/Content/style.css" type="text/css" />
Source

In my case, I find #Href not being enough in the way it deals with query strings in a URL. I prefer to wrap it inside the Raw method:
<script>
var isKendoWindow = false;
var myTimeOut;
clearTimeout(myTimeOut);
var sessionTimeout = (#Session.Timeout * 60000) - 5;
function doRedirect() {
if (!isKendoWindow)
window.location.href = '#Html.Raw(Href("~/Logon.aspx?brandid=" + SessionController.LandingBrandId + "&errCode=5055"))';
}
myTimeOut = setTimeout('doRedirect()', sessionTimeout);
</script>
Or you can create your own version like this:
public static IHtmlString ResolveUrl(this HtmlHelper htmlHelper, string url)
{
var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
return htmlHelper.Raw(urlHelper.Content(url));
}

Another way to solve this issue:
Resolve the url in a code block at the top of the page or in code behind.
#page
#model IndexModel
#{
ViewData["Title"] = "Home page";
Layout = "~/Pages/Shared/_IndexLayout.cshtml";
String img1 = Url.Content("~/img/people11.jpg");
}
Then use the variable in the html.
<div class="col-12 col-lg-8" style="background-image: url('#img1');"> </div>

Server.MapPath() //returna full path
or
url.content()

try using Server.MapPath().

Related

Where are #Json.Encode or #Json.Decode methods in MVC 6?

What is equivalent of MVC5's #Json.Encode method in MVC6? In MVC5 we can access those methods in views. But I can't find any methods which I can access from MVC 6 views.
I don't want to write a helper method if there is already a built in feature in MVC6.
After some search, found it:
#inject IJsonHelper Json;
#Json.Serialize(...)
I've had success with the following:
#Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(myObj) as String)
I'm not sure if Json.Encode has made it in yet because it was a part of System.Web which is gone now.
One of the features of #Json.Encode() was automatic HTML encoding of entities within JSON strings, which is helpful to avoid XSS vulnerabilities. The JsonHelper class is based on Json.NET serialization now, which does support at least some (or all) of this same functionality if configured properly. The other solutions here can be vulnerable to XSS attacks if untrusted data is serialized.
Quick example of a vulnerability:
<script>
window.something = #Json.Serialize(new { someprop = "Hello</script><script>alert('xss')</script><script>" });
</script>
Will be rendered as
<script>
window.something = {"someprop":"Hello
</script>
<script>alert('xss')</script>
<script>"};</script>
To properly configure Json.NET to escape HTML entities would be to use the #Json.Serialize(object, serializerSettings) overload and override StringEscapeHandling to EscapeHTML. The settings could be defined in a helper class or injected.
#using Newtonsoft.Json
<script>
#{
var settings = new JsonSerializerSettings {StringEscapeHandling = StringEscapeHandling.EscapeHtml};
}
window.something = #Json.Serialize(new { someprop = "Hello</script><script>alert('xss')</script><script>" }, settings);
</script>
Which is rendered instead as:
<script>
window.something = {"someprop":"Hello\u003c/script\u003e\u003cscript\u003ealert(\u0027xss\u0027)\u003c/script\u003e\u003cscript\u003e"};
</script>
Some other methods of safely serializing data to the page in ASP.NET Core can be found here: https://github.com/aspnet/Docs/blob/master/aspnetcore/security/cross-site-scripting.md

Get Relative Url in ASP.NET MVC View

I have an ASP.NET MVC app. I am using Razor in my views. Due to my IT dept. the app sits at a relative root like http://ourdomain.com/appRoot instead of at the top of the domain like http://ourdomain.com. The other challenge here is, appRoot is not static. It actually changes. For that reason, I need to get the name of the relative root via Razor. Currently, I have something like the following:
<input id="hiddenElem" type="hidden" value="12345" />
<script type='text/javascript'>
function doThis() {
var id = $('#hiddenElem').val();
var nextUrl = '#(Request.?)' + '/path/' + id;
alert(nextUrl);
}
</script>
When doThis is called, I want to see the alert window to display /appRoot/path/12345. What do I put into the Razor block associated with nextUrl to get the relative root?
Generally you would use the mvc routing function Url.Action().
function doThis() {
var id = $('#hiddenElem').val();
var nextUrl = '#Url.Action("MyAction","MyController")' + '/path/' + id;
alert(nextUrl);
}
The Html.ResolveUrl() function is fine for resolving relative paths, however, it does not take into consideration routing.
Also, using the Url.Content() function may produce a result you are expecting. For example, in the snippet below:
.Template("<img src='"+ #Url.Content("~/Images/Icons/16/STATE.png")+"'/> <mark>${data.StateName }</mark>");
The image will always resolve no matter where you are calling it from or how you accessed the view withing the root.

Can a utility method return raw html in MVC razor

I am trying to output a value to the page using MVC razor of autoplay='autoplay' in order to autoplay HTML5 video. My method GetAutoPlayVideo reads the web.config file to determine if the site will autoplay the videos.
public static string GetAutoPlayVideo()
{
bool autoPlayVideo = Converter.ToBoolean(System.Web.Configuration.WebConfigurationManager.AppSettings["AutoPlayVideo"]);
if (autoPlayVideo)
return "autoplay='autoplay'";
else
return string.Empty;
}
Then on the page use the following markup:
<div id="videoHolder">
<video id="video" width="503" height="284" #Html.Raw(MyUtility.GetAutoPlayVideo()) controls >
#foreach (string s in Model.SelectedShow.VideoFiles)
{
<source src="#(CdnResources.GetImageUrl(s))" type="#(Utility.GetMimeType(s))" />
}
Your browser does not support the video tag.
</video>
</div>
The syntax I have created so far is this:
#Html.Raw(MyUtility.GetAutoPlayVideo())
is it possible to shorten this up to something like?
#MyUtility.GetAutoPlayVideo()
Yes.
The Razor escaping system will not escape anything of type IHtmlString. The Html.Raw() method simply returns an HtmlString instance containing your text.
You can simply declare your method as returning IHtmlString, and call Html.Raw() (or new HtmlString() inside.

Escaping JavaScript string literals in views

Is there a utility function for escaping JavaScript in ASP.NET MVC views? I often need to init a little snippet of JavaScript using some values from the view; for instance I may have something like:
<script type="text/javascript">
var page = new Page({ currentUser: "<%= Model.UserName %>" });
page.init();
</script>
I would expect something like:
<script type="text/javascript">
var page = new Page({ currentUser: "<%= Html.JavaScriptEscape(Model.UserName) %>" });
page.init();
</script>
I could, of course, write the function myself. But since there are already built-in utilities form HTML encoding, and since one of the selling points of ASP.NET MVC is that the <% %> is the default rendering mode, and since what I'm trying to achieve is quite common, it makes me wonder why I cannot find anything like that already built-in. Is there, for instance, an easy and elegant way to serialize an object to JSON in views?
Or am doing something against ASP.NET MVC principles? When I hit a problem like this, it usually makes it think that either I’m doing something wrong since I assume that the framework designers spent some time thinking about real world scenarios.
In .NET 4, The HttpUtility class has a variety of static encoding methods for various contexts, including a JavaScriptStringEncode method for this particular purpose.
It's often simpler to just use JSON deserialization, though.
In MVC 5 using Razor templates, the following is possible:
<script type="text/javascript">
var page = new Page({ currentUser: #Html.Raw(Json.Encode(Model.UserName)) });
page.init();
</script>
After some time working in ASP.NET MVC, I concluded that (most likely) there is no build-in helper for it. Of course, it's trivial to write your own. Here is it for the sake of completeness:
using System.Web.Mvc;
using System.Web.Script.Serialization;
namespace MyProject.Helpers
{
public static class JsonExtensions
{
public static string Json(this HtmlHelper html, object obj)
{
JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();
return jsonSerializer.Serialize(obj);
}
}
}
In a view, it can be used as follows:
<script type="text/javascript">
var page = new Page(<%= Html.Json(new { currentUser: Model.UserName } ) %>);
page.init();
</script>
In my case I needed a string not a json object and this is for Asp.Net Core:
#functions{
public Microsoft.AspNetCore.Html.IHtmlContent ToJS(string value)
{
return Html.Raw("'" + value.Replace("'", "\\'").Replace("\r", "\\r").Replace("\n", "\\n") + "'");
}
public Microsoft.AspNetCore.Html.IHtmlContent ToJS(int value)
{
return Html.Raw("" + value);
}
}
This will escape the ' and end of line characters. Also it leaves numbers (int) as a number. This could be overloaded to include float, decimal, etc. as needed.
So, I don't have to think about it or do anything different for each type:
var serverName = #ToJS(m.ServerName);
var appSiteUrl = #ToJS(m.SiteUrl);
var facebookId = #ToJS(m.FacebookAppId);

Inline Code on Webform Property

Why doesn't this display the date/time when rendered?
<asp:Label runat="server" ID="test" Text="<%= DateTime.Now.ToString() %>" ></asp:Label>
Is there anyway to make this work?
Asp.net server controls don't play well with the <%=, instead you can do:
<span><%= DateTime.Now.ToString() %></span>
Ps. you could alternatively set the label's text on the code-behind. It might work for your scenario to set it on the PreRenderComplete.
I'm not sure if you've got a code behind file, but if you really need to set the label's Text property in the .aspx markup you could add the following code to the page:
<script runat="server">
protected override void OnPreLoad(EventArgs e)
{
if (!Page.IsPostBack)
{
this.test.Text = DateTime.Now.ToString();
base.OnPreLoad(e);
}
}
</script>
This way you can maintain the label control's state on postback.
Put the inline code inside the label's tag as below,
< asp:Label ID="Lbl" runat="server" Text="">
<%= DateTime.Now.ToString() %>
< /asp:Label>
Well the asp tags are rendered. You will have to set the property at runtime. or just do the <%= DateTime.Now.ToString() %>.
The simplest way to make that work would be to use a data-binding expression in place of the code render block...
<asp:Label runat="server" ID="test" Text="<%# DateTime.Now.ToString() %>" ></asp:Label>
Now the Text property will be set whenever Page.DataBind() is called, so in your code-behind you'll want something like
protected override void OnPreRender(EventArgs e)
{
if (!Page.IsPostBack)
{
DataBind();
}
base.OnPreRender(e);
}
The real problem here though is I need to set the property of a WebControl with code on the markup page. The only way I've found to do this is put the whole control in a code block. Its not elegant or suggested but when all else fails this will work.
<%
var stringBuilder = new StringBuilder();
var stringWriter = new StringWriter(stringBuilder);
var htmlWriter = new HtmlTextWriter(stringWriter);
var label = new Label { Text = DateTime.Now.ToString() };
label.RenderControl(htmlWriter);
Response.Write(stringBuilder.ToString());
%>
But this won't work if you need the control to maintain state.
UPDATE:
After researching Kev's answer I did find an even better solution. I don't have a code behind (its an MVC page) but you can still reference a control on the page through a code block so my new solution is the following. Note - You have to place the code block first for this to work.
<%
lblTest.Text = DateTime.Now.ToString();
%>
<asp:label runat="server" ID="lblTest" />
Thanks for the inspiration Kev!

Resources