ASP .NET MVC3 ViewBag sanitizing string - c#

So I need to pass to a JavaScript function an array of strings in my view based on data from the database. So I have this code in the controller:
string top_six_string = "[";
foreach (ObjectModel om in collection)
{
myProject.Models.BlobFile file = null;
if (om.BlobFile != null)
{
file = om.BlobFile;
}
else if (om.BlobFiles.Count != 0)
{
file = om.BlobFiles.First();
}
if (file != null)
{
top_six_string += " \"" + file.BlobFileID + "\",";
}
}
top_six_string = top_six_string.TrimEnd(',');
top_six_string += "]";
ViewBag.TopSixList = top_six_string;
Now, I don't particularly understand why we have both a BlobFile field and a BlobFiles collection, but that's not that point. The point is, debugging shows that I accurately the get the string I want (of the form ["25", "21", "61", "59"]).
But when running the JavaScript, I got the confusing error "Unexpected character &", and a little source-viewing in Chrome led me to learn that the string came out looking like this:
[ "25", "21", "61", "59"]
So my assumption is that the ViewBag is sanitizing string that it is passed for display in HTML, but obviously that isn't my concern right now. Am I correct in my assumption? Is there another way to pass the view this information? Is there a way I can coerce the string back to quotes afterwards?

The problem is most likely when you output the contents of the ViewBag in your View. By default the Html helpers sanitize output to help protect against injection attacks.
What you want is this when outputting the value in your View: #Html.Raw(ViewBag.TopSixList)

Since programmers barely use MVC3 and google shows this page also for Asp core
In ASP.Net Core change this line :
ViewBag.TopSixList = top_six_string;
To
ViewBag.TopSixList = new HtmlString(top_six_string);
And add using Microsoft.AspNetCore.Html; if HtmlString is not accessible.

Related

String encoding during page render

I am experiencing an odd problem as the page is being rendered in the browser, or so it seems.
In the Model I have
public string ReviewWrapperUrl
{
get
{
string returnurl = Settings.SiteSettings.SiteRoot + Settings.PowerReviewSettings.CCReviewWrapperUrl + PageID;
if (!string.IsNullOrEmpty(Year))
{
returnurl = returnurl + "&pr_page_id_variant=" + Year;
}
return returnurl;
}
}
At this point returnurl holds a value like http://www.mydomain.co.uk/write-a-review?page_id=191519&pr_page_id_variant=2018
In the cshtml I have:
<script>
try {
POWERREVIEWS.display.render({
api_key: "#Model.PowerReviewAPIKey",
locale: "en_GB",
merchant_group_id: "#Model.PowerReviewMerchantGroupID",
merchant_id: "#Model.PowerReviewMerchantID",
page_id: "#Model.PageID",
review_wrapper_url: "#Model.ReviewWrapperUrl",
components: {
ReviewSnippet: 'pr-reviewsnippet',
ReviewImageDisplay: 'pr-reviewimagedisplay',
ReviewDisplay: 'pr-reviewdisplay'
}
});
} catch (e) {
window.console && window.console.log(e);
}
</script>
If I put a breakpoint on review_wrapper_url: "#Model.ReviewWrapperUrl", the value is the same.
Here is where is get more complicated. The powerreviews plugin then renders to the browser. However by the time it is rendered the string has somehow been encoded. The & in page_id=191519&pr_page_id_variant=2018 has changed to & and this is causing me problems because the plugin on the target page is using & as a delimiter.
I have spoken to Power Reviews and they have tried the same values and cannot replicate the problem. One of their developers that knows a little c#/APSX has suggested it could be that .NET is somehow converting it as its being rendered.
However the final URL has been appended with more parameters by the Power Review plugin which are not affected.
http://www.mydomain.co.uk/write-a-review?page_id=191519&pr_page_id_variant=2018&pr_merchant_id=xxxxxx&pr_api_key=xxx-xxxx-xxx-xxxx-xxxxxxxxx&pr_merchant_group_id=xxxxx
Has anyone experienced this? Suggest ways for me to prove or disprove processes that may be causing it?

Throwing a popup when search yields no results

Here's the deal. Have a functioning web app using ASP.NET WebForms with a C# backend. The thing works fine, but I'm always looking to improve, as a beginner at this stuff. Right now, to deal with a user's search coming back with no results, I utilize the following, and was wondering if there was any cleaner way to do it, for future reference:
DataClass data = new DataClass();
var searchresults = data.GetData(searchBox.Text);
int datanumber = searchresults.Count();
if (datanumber == 0)
{
ClientScript.RegisterStartupScript(this.GetType(), "alert", "javascript:alert('There were no records found to match your search');", true);
}
else
{
DropDownList1.Visible = true;
DropDownList1.Items.Clear();
DropDownList1.DataSource = searchresults;
DropDownList1.DataBind();
}
I agree with the not using popups, so you could always do something as simple as having a Label object on your page:
<asp:Label runat="server" id="lblResultMsg" ForeColor="Red" Visible="False" />
And then set the text dynamically (or add it as a property to the code) and set the label to be visible on postback if no results are found:
if (datanumber == 0)
{
lblResultMsg.Text = "There were no records found to match your search.";
lblResultMsg.Visible = true;
}
else
{
lblResultMsg.Text = "";
lblResultMsg.Visible = false;
// do your data binding
}
But there are quite a vast number of ways you could achieve something like this. Regarding your question about using the .Count from the Enumerable collection - there's nothing stopping you doing this as it's perfectly valid. The question is which method do you find more readable?
if you include the jquery ui dialog (http://jqueryui.com/demos/dialog/), you can simply call this to create a nice dialog box:
$('<div>message</div>').dialog({autoOpen:true,title:'Error'});
Personally I prefer to create a helper function for inserting the relevant javascript into the page, and only pass parameters to the function so that I don't need to worry about the messy details every time.
Something like :
public static void GrowlMessage(System.Web.UI.Control pageControl, string header = "", string message = "", bool sticky = false, string position = "top-right", string theme = "", bool closer = true, int life = 8)
{
string _js = "$.jGrowl('" + HttpContext.Current.Server.HtmlEncode(message) + "', { header:'" + header + "', sticky:" + sticky.ToString().ToLower() + ", position: '" + position + "', theme: '" + theme + "', closer: " + closer.ToString().ToLower() + ", life:" + life * 1000 + "});";
ScriptManager.RegisterStartupScript(pageControl, pageControl.GetType(),"Growl",_js, true);
}
The sample I have used also requires jQuery and the jGrowl library available here. And IMHO the messages are pretty. They are unobtrusive, the user does not need to click a button to make them go away, and they fade away after your specified amount of time.
But I agree with Mike, that if you don't have any records, you should just use the built in properties of a GridView (EmptyDataRowStyle and EmptyDataRowText) to display a 'no data matching your query' style message. Assuming that you're using a GridView at all, that is..
When it comes to user feedback, Impromptu is my friend. There is a nice ASP.NET implementation of Impromptu on Aaron Goldenthal's website: http://www.aarongoldenthal.com/post/2009/11/11/Using-jQuery-Impromptu-With-ASPNET.aspx
If you have decided to alert user via alert then please go ahead with light box effect..
http://www.designyourway.net/blog/resources/30-efficient-jquery-lightbox-plugins/
if you are still would like to go ahead with traditional alert then obviously its easy for you to fire it up on page load rather than attaching script to it..
')" ....>
Because if you require any change then you just need to alter the javascript alone and you dont need to build project again to test it...
Hope its useful for you..
Note: I'm using my own DLLs to render content so above coding may requires alteration because i did forget traditional asp codings.. :)

Get a sitemap in ASP.NET part from Umbraco

I have a website which has two parts: the first one was made in Umbraco CMS (v4.7), the second one in ASP.NET.
The task is to get a sitemap (not just names of pages, I need some parameters as well) in ASP.NET part from Umbraco.
I have only one idea how I can do such thing - write an XML file in Umbraco and then open it in ASP.NET, but I did not find any way how exactly do it.
If you have any ideas, please help.
Many Thanks
Vlad
you can do something like this...
using umbraco.presentation.nodeFactory;
public string CreateSitemap()
{
var temp = "<ul>" + sitemap(-1) + "</ul>";
return temp;
}
public string sitemap(int nodeID)
{
var rootNode = new umbraco.presentation.nodeFactory.Node(nodeID);
string sitemapstring = "<li>" + rootNode.Name + "</li>";
if(rootNode.Children.Count>0)
{
sitemapstring+="<ul>";
foreach(Node node in rootNode.Children)
{
sitemapstring += sitemap(node.Id);
}
sitemapstring+="</ul>";
}
return sitemapstring;
}
Maybe you should check out the Razor edition of this sitemap package (at the bottom)?

remove html tags or script tags in c# string and also in client using javascript

I need to do a user input validation, and I want it validated both in the client side and in the server side.
I have ang textbox that the user can write his comment on the product, now what I wanted to do is to validate if his comment doesn't have any injections like html or javascripts. So what I wanted to do, after the user clicks on submit
1.) Client Side: How will I execute a validation like if the user inputs this kinds of string
abcd // I will accept only abcd and remove the anchor tag but the abcd should appear as a link
<script type="text/javascript">alert(123);</script> // I will accept only alert(123);as the valid string
<b>abcd</b> // I will display abcd but it must appear bold
2.) Server side: Same situation with the client side, I will remove the tags of the injected script and html tags.
I am using sharepoint 2007, I'm not sure if there is a built-in function to do this kind of validation in sharepoint api or c# for the server side validation.
Note: I don't want to use RegEx for this or any third party software. I know many experts here can help me with this. Thank you so much!
While RegEx is probably your best bet, you can use this and modify to your liking:
public static string StripHtml(this string source)
{
string[] removeElements = new string[] { "a", "script" };
string _newString = source;
foreach (string removeElement in removeElements)
{
while (_newString.ToLower().Contains("<" + removeElement.ToLower()))
{
_newString = _newString.Substring(0, _newString.ToLower().IndexOf("<" + removeElement.ToLower())) + _newString.Substring(_newString.ToLower().IndexOf("</" + removeElement.ToLower() + ">") + removeElement.Length + 3);
}
}
return _newString;
}
You'll use string clean = txtInput.Text.StripHtml();
I am not sure about creating an validation for this. But you can programtically remove the tags using this function.
Use this function to remove the Html tage from the textbox value that user has input
public static string StripHtml(string html, bool allowHarmlessTags)
{
if (html == null || html == string.Empty)
return string.Empty;
if (allowHarmlessTags)
return System.Text.RegularExpressions.Regex.Replace(html, "", string.Empty);
return System.Text.RegularExpressions.Regex.Replace(html, "<[^>]*>", string.Empty);
}
If you want prevent javascript injection attacks just encode user input Server.HtmlEncode(message).
But if you need to clean some tags then Omar Al Zabir wrote good article Convert HTML to XHTML and Clean Unnecessary Tags and Attributes
// Encode the string input
StringBuilder sb = new StringBuilder(
HttpUtility.HtmlEncode(htmlInputTxt.Text));
// Selectively allow <b> and <i>
sb.Replace("<b>", "<b>");
sb.Replace("</b>", "");
sb.Replace("<i>", "<i>");
sb.Replace("</i>", "");
Response.Write(sb.ToString());
I also would like to recomand you check AntiSamy.NET project but I didn't try it by myself.

Persist data using JSON

I'm tryping to use JSON to update records in a database without a postback and I'm having trouble implementing it. This is my first time doing this so I would appreciate being pointed in the right direction.
(Explanation, irrelevant to my question: I am displaying a list of items that are sortable using a jquery plugin. The text of the items can be edited too. When people click submit I want their records to be updated. Functionality will be very similar to this.).
This javascript function creates an array of the objects. I just don't know what to do with them afterwards. It is called by the button's onClick event.
function SaveLinks() {
var list = document.getElementById('sortable1');
var links = [];
for (var i = 0; i < list.childNodes.length; i++) {
var link = {};
link.id = list.childNodes[i].childNodes[0].innerText;
link.title = list.childNodes[i].childNodes[1].innerText;
link.description = list.childNodes[i].childNodes[2].innerText;
link.url = list.childNodes[i].childNodes[3].innerText;
links.push(link);
}
//This is where I don't know what to do with my array.
}
I am trying to get this to call an update method that will persist the information to the database. Here is my codebehind function that will be called from the javascript.
public void SaveList(object o )
{
//cast and process, I assume
}
Any help is appreciated!
I have recently done this. I'm using MVC though it shouldn't be too different.
It's not vital but I find it helpful to create the contracts in JS on the client side and in C# on the server side so you can be sure of your interface.
Here's a bit of sample Javascript (with the jQuery library):
var item = new Item();
item.id = 1;
item.name = 2;
$.post("Item/Save", $.toJSON(item), function(data, testStatus) {
/*User can be notified that the item was saved successfully*/
window.location.reload();
}, "text");
In the above case I am expecting text back from the server but this can be XML, HTML or more JSON.
The server code is something like this:
public ActionResult Save()
{
string json = Request.Form[0];
var serializer = new DataContractJsonSerializer(typeof(JsonItem));
var memoryStream = new MemoryStream(Encoding.Unicode.GetBytes(json));
JsonItem item = (JsonItem)serializer.ReadObject(memoryStream);
memoryStream.Close();
SaveItem(item);
return Content("success");
}
Hope this makes sense.
You don't use CodeBehind for this, you use a new action.
Your action will take an argument which can be materialized from your posted data (which, in your case, is a JavaScript object, not JSON). So you'll need a type like:
public class Link
{
public int? Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Url { get; set; }
}
Note the nullable int. If you have non-nullable types in your edit models, binding will fail if the user does not submit a value for that property. Using nullable types allows you to detect the null in your controller and give the user an informative message instead of just returning null for the whole model.
Now you add an action:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult DoStuff(IEnumerable<Link> saveList)
{
Repository.SaveLinks(saveList);
return Json(true);
}
Change your JS object to a form that MVC's DefaultModelBinder will understand:
var links = {};
for (var i = 0; i < list.childNodes.length; i++) {
links["id[" + i + "]"] = list.childNodes[i].childNodes[0].innerText;
links["title[" + i + "]"] = list.childNodes[i].childNodes[1].innerText;
links["description[" + i + "]"] = list.childNodes[i].childNodes[2].innerText;
links["url[" + i + "]"] = list.childNodes[i].childNodes[3].innerText;
}
Finally, call the action in your JS:
//This is where I don't know what to do with my array. Now you do!
// presumes jQuery -- this is much easier with jQuery
$.post("/path/to/DoStuff", links, function() {
// success!
},
'json');
Unfortunately, JavaScript does not have a built-in function for serializing a structure to JSON. So if you want to POST some JSON in an Ajax query, you'll either have to munge the string yourself or use a third-party serializer. (jQuery has a a plugin or two that does it, for example.)
That said, you usually don't need to send JSON to the HTTP server to process it. You can simply use an Ajax POST request and encode the form the usual way (application/x-www-form-urlencoded).
You can't send structured data like nested arrays this way, but you might be able to get away with naming the fields in your links structure with a counter. (links.id_1, links.id_2, etc.)
If you do that, then with something like jQuery it's as simple as
jQuery.post( '/foo/yourapp', links, function() { alert 'posted stuff' } );
Then you would have to restructure the data on the server side.

Categories

Resources