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
Related
I am 3 months into learning KnockoutJS and it has been great so far. However, I am facing an issue with binding.
This is the scenario:
I am using MVC with KO.
MVC model is passed down to the view, converted into a knockout object and pushed into the viewModel variable:
var data = ko.mapping.fromJS(#Html.Raw(Json.Encode(Model)));
var viewModel = new HP.ViewModels.CertificationPathViewModel(data);
ko.applyBindings(viewModel);
Within viewModel, I reference the MVC model as self.data:
ViewModels.CertificationPathViewModel = (function (data) {
var self = ViewModels.BaseEntityViewModel.apply(this, [data]);
// some other code
return { Data: self.Data, };
}
ViewModels.BaseEntityViewModel = (function (data) {
var self = this;
self.data = ko.observable(data);
// other code
return { Data: self.data, };
}
On the view, I data-bind like this:
<div id="drpControl" data-bind="CustomDropdown: Data().BusinessUnits.SelectedGroup, optionSettings: { CustomOptions: Data().Units.Groups, CustomOptionsCaption: '-- Select Group --' }"></div>
I try to update the self.data after an ajax call. I return the entire MVC model object and attempt to replace self.data like this :
self.data(updatedModel)
My expectation is that KO will take care of the update and no extra binding is needed. It works great for simple binding (ex. Value: Data().Something) but it doesn't work for complex binding (ex. value: Data().BusinessUnits.SelectedGroup ).
The controls that have complex binding are still bound to the old model, so KO doesn't know what to pass back next time I submit an ajax request.
Is this a limitation of KO, or I am not doing something properly?
Thanks
the ko.mapping plugin changes every property on self.data into an observable. During your update, you need to remap the updated data.
Since you didn't actually post your code, just unformatted snippets I can't help a whole bunch, but you should start by changing this line: self.data(updatedModel) to this:
ko.mapping.fromJS(updatedModel, self.data);
see the Knockout.JS mapping documentation
Protip for stack overflow - include your full code, to the extent that it's possible. Also, if you can, make a jsfiddle that reproduces your problem.
I'm using Handlebars.js, and currently all my templates live inside script tags which live inside .html files housing dozens of other templates, also inside script tags.
<script type="text/template" id="template-1">
<div>{{variable}}</div>
</script>
<script type="text/template" id="template-2">
<div>{{variable}}</div>
</script>
<script type="text/template" id="template-3">
<div>{{variable}}</div>
</script>
...
Then I include this file on the server-side as a partial.
This has the following disadvantages:
A bunch of templates are crammed into HTML files.
Finding a given template is tedious.
I'm looking for a better way to organize my templates. I'd like each each template to live in its own file. For example:
/public/views/my_controller/my_action/some_template.html
/public/views/my_controller/my_action/some_other_template.html
/public/views/my_controller/my_other_action/another_template.html
/public/views/my_controller/my_other_action/yet_another_template.html
/public/views/shared/my_shared_template.html
Then at the top of my view, in the backend code, I can include these templates when the page loads, like this:
SomeTemplateLibrary.require(
"/public/views/my_controller/my_action/*",
"/public/views/shared/my_shared_template.html"
)
This would include all templates in /public/views/my_controller/my_action/ and also include /public/views/shared/my_shared_template.html.
My question: Are there any libraries out there that provide this or similar functionality? Or, does anyone have any alternative organizational suggestions?
RequireJS is really good library for AMD style dependency management. You can actually use the 'text' plugin of requireJS to load the template file in to your UI component. Once the template is attached to the DOM, you may use any MVVM, MVC library for bindings OR just use jQuery events for your logic.
I'm the author of BoilerplateJS. BoilerplateJS reference architecture uses requireJS for dependency management. It also provides a reference implementations to show how a self contained UI Components should be created. Self contained in the sense to handle its own view template, code behind, css, localization files, etc.
There is some more information available on the boilerplateJS homepage, under "UI components".
http://boilerplatejs.org/
I ended up using RequireJS, which pretty much let me do this. See http://aaronhardy.com/javascript/javascript-architecture-requirejs-dependency-management/.
I use a template loader that loads the template using ajax the first time it is needed, and caches it locally for future requests. I also use a debug variable to make sure the template is not cached when I am in development:
var template_loader = {
templates_cache : {},
load_template : function load_template (params, callback) {
var template;
if (this.templates_cache[params.url]){
callback(this.templates_cache[params.url]);
}
else{
if (debug){
params.url = params.url + '?t=' + new Date().getTime(), //add timestamp for dev (avoid caching)
console.log('avoid caching url in template loader...');
}
$.ajax({
url: params.url,
success: function(data) {
template = Handlebars.compile(data);
if (params.cache){
this.templates_cache[params.url] = template;
}
callback(template);
}
});
}
}
};
The template is loaded like this:
template_loader.load_template({url: '/templates/mytemplate.handlebars'}, function (template){
var template_data = {}; //get your data
$('#holder').html(template(template_data)); //render
})
there's this handy little jquery plugin I wrote for exactly this purpose.
https://github.com/cultofmetatron/handlebar-helper
I have just started using the
<% Html.DevExpress().DateEdit()
control and i got it to work fine in my ASP.Net MVC application. The code is as shown below:
aspx page:
<% Html.DevExpress().DateEdit(settings =>
{
settings.Name = "EndDate";
settings.Properties.NullText = "dd/MM/yyyy";
settings.Properties.EditFormat = EditFormat.Custom;
settings.Properties.EditFormatString = "dd/MM/yyyy";
settings.Properties.DisplayFormatString = "dd/MM/yyyy";
settings.Date = Model.EndDate;
settings.Width = 100;
}
).Render();
%>
Above this code i have a reference to my javascript file (DateChanges.js) in this file i want to be able to do something like:
$(document).ready(function(){
$("#EndDate").change(function(){
//do whatever i want
});
})
I cant do this now cause using firefox i can see that the actual textbox that this datepicker assigns a value to has be named "EndDate_I". So my question is how can i easily do this since i want to be able to catch the change event of this control and play around with it in jQuery??
The DevExpress MVC Extensions offer their own infrastructure for the client-side processing needs (see the http://help.devexpress.com/#AspNet/CustomDocument6908 help topic to getting started).
It is necessary to handle the client-side ASPxClientDateEdit.DateChanged event, and retrieve the newly selected Date via the client-side ASPxClientDateEdit.GetDate() method. Use the retrieved js Date object for your additional needs:
<script type="text/javascript">
function OnDateChanged(s, e) {
var newDate = s.GetDate();
alert(newDate);
}
</script>
settings.Properties.ClientSideEvents.DateChanged = "OnDateChanged";
There is a rather long Blog post at http://kennytordeur.blogspot.com/2011/05/aspnet-mvc-where-is-clientid_10.html discussing your problem
( I think it is to long to have it pasted here, and the author deserves the credits )
following on from your comment on Mikhails's answer, there will be a property in the global namespace with the name of your control, so it's just like this:
CalculateDayDifference(s.GetDate(), EndDate.GetDate());
All the mvc controls do this, for some you might have to set the EnableClientSideApi property to start using them.
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().
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);