Json.stringify allows HTML elements - javascript

I am trying to post values from MVC view to controller.
Request validation feature is enabled for application.
But when i tried to pass values with HTML tags to controller, I am not getting any exception.
here is my ajax post:
Group.Name = model.Name();
Group.Id = model.ID();
$.ajax({
type: 'POST',
url: /IndexController/SaveGroup',
async: true,
cache: false,
dataType: "json",
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ Group: group }),
success: function (data /*, textStatus, request*/) {
try {
}
catch (error) {
showExceptionWindow('Jquery Error:' + error);
}
},
error: function (request /*, status, error*/) {
handleException(request.responseText);
}
});
}
Controller Code:
[HttpPost]
public async Task<ActionResult> SaveGroup(Group group)
{
when i tried to insert html tags,the values are passing to controller action method and getting saved.
When request validation feature is enabled,html elements should not be passed to controller.
How to make sure it is getting blocked at controller.

MVC validation dosent work since you've changed the submit button to prevent default mvc use the jquery plugin Validate.js just go through i,this code should work
var form = $("#YourFormID");
form.validate();
form.submit(function (e) {
e.preventDefault();
if (form.valid()) {
//Your ajax call
}
})

Seems you have a typo as there group does not seem to be a valid object it is undefined:
data: JSON.stringify({ group: Group }), // <-----It should have to be this Group here
And at your backend:
[HttpPost]
public async Task<ActionResult> SaveGroup(Group group) // group is {}
{
Or as Group is already an object then you can stringify it directly:
data: JSON.stringify(Group), // <-----It should have to be this Group here
[HttpPost]
public async Task<ActionResult> SaveGroup(Group Group) // group is {}
{

Why not using an HTML parser to detect HTML elements injection? This can be a clean JS solution
var containsHTML = /<[a-z][\s\S]*>/i.test("<p>HTML text to be parsed</p>")
if(containsHTML==true){
//There are HTML tags inside the string
}
else{
//You're good to go
}

Related

Passing parameters in Ajax post back in MVC

I am trying to pass ID parameter from a view to a controller on a click delete link available on a selected row.
Simplified View Layout
#using (Html.BeginForm("#", "Schedule", FormMethod.Post, htmlAttributes: new { #class = "floating-labels" }))
{
#Html.AntiForgeryToken()
Delete
}
JavaScript
<script type="text/javascript">
function DeleteSchedule(id) {
if (confirm('Are you sure you want to delete this Schedule?')) {
$.ajax({
type: "POST",
url: '#Url.Action("Delete", "Schedule", new { id = "id" })',
contentType: "application/json",
data: { id },
async: true,
cache: false,
success: function (result) { success(result); }
});
}
return false;
}
function success(result) {
$("#ScheduleList").html(result);
}
</script>
Controller
namespace Controllers
{
public class ScheduleController
{
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Delete(int id)
{
//do stuff
}
}
}
But on the click of a delete link I get below error and code does not hit controller action.
I am not able to figure out what mistake I am making...
Here is my locally tested implementation that is working.
ScheduleController class:
public class ScheduleController : Controller
{
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Delete(int id)
{
return Ok(id);
}
}
Page that sends the post request:
#Html.AntiForgeryToken()
Delete
<div id="ScheduleList"></div>
<script>
function DeleteSchedule(id) {
if (confirm('Are you sure you want to delete this Schedule?')) {
var uri = '/Schedule/Delete?id=' + id;
var tokenElement = document.getElementsByName('__RequestVerificationToken')[0];
var data = {
__RequestVerificationToken: tokenElement.value
}
$.ajax({
type: "POST",
url: uri,
data: data,
success: function (result) {
success(result);
}
});
}
return false;
}
function success(result) {
$("#ScheduleList").html(result);
}
</script>
The page does nothing but render the html, and the javascript handles the actual Ajax post. What I believe you were missing is the Validation token in your request.
It is because you are not actullay posting the form pass it correctly and add _token in the ajax data list and value for that token will come from #Html.AntiforgeryToken()
reading the error the request is most probably send correctly and there is an internal server error as mentioned in the 500 respond so please check the code that is inside the controller
Try this, you are accesing a javascript variable on c# code, and you cant do that.
If correct, please mark as answer.
function DeleteSchedule(id) {
if (confirm('Are you sure you want to delete this Schedule?')) {
var url = '#Url.Action("Delete", "Schedule")?id=' + id;
$.ajax({
type: "POST",
url: url,
contentType: "application/json",
data: { id },
async: true,
cache: false,
success: function (result) { success(result); }
});
}
return false;
}
I think none of the answers above solve the issue. First of all I would replace your target url:
url: '#Url.Action("Delete", "Schedule", new { id = "id" })',
with
url: '#Url.Action("Delete", "Schedule", new { id = actualIdVariable })',
(replace "id" with the actual id variable from the model you're passing to the view).
Note how your browser response is telling you that the url you're posting to is Schedule/Delete/id. That said, I'm not sure you even need the routeValues in this case (the new { id = ...} parameter). this is a POST action, and action parameters wouldn't come from route unless specified by by attribute routing (i.e. [Route("~/Schedule/Delete/{id}")] attribute on your action).
I think your post action is failing because it is trying to parse the "id" string as an int.
Second, I would change the data property of the ajax call and include the anti forgery token. Just because the anchor element you're binding the click event to, is inside the form with #Html.AntiforgeryToken() doesn't mean the generated token will be posted in the ajax request. You're not actually submitting/posting the form, you're just clicking a button.
it should be something like
data: {
'id': id,
'__RequestVerificationToken': $('[name="__RequestVerificationToken"]').val()
}
try this, it solve the error on routing (different url Action) and the parameter on the controller:
JavaScript
<script type="text/javascript">
function DeleteSchedule(id) {
if (confirm('Are you sure you want to delete this Schedule?')) {
$.ajax({
type: "POST",
url: '#Url.Action("Delete", "Schedule")',
data: "id=" + id ,
async: true,
cache: false,
success: function (result) { success(result); }
});
}
return false;
}
function success(result) {
$("#ScheduleList").html(result);
}
</script>
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Delete(string id)
{
//do stuff
}
Nicola.

jQuery API call to Entity Framework API Put method

I am using jquery to make an API call to an Entity Framework API Controller and I am trying to call the Put Method:
[ResponseType(typeof(void))]
public IHttpActionResult PutProfileIDClass(int id, ProfileIDClass profileIDClass)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != profileIDClass.id)
{
return BadRequest();
}
db.Entry(profileIDClass).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!ProfileIDClassExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
But when I make the API call via jQuery I get this error: 405 (Method Not Allowed)
What Am I doing wrong?
Here is my API call
var data = {
id: result.data[0].id,
profileID: result.data[0].profileID,
taken: 'true'
};
var json = JSON.stringify(data);
$.ajax({
url: '/api/ProfileIDAPI?id=' + result.data[0].id,
type: 'PUT',
contentType: "application/json; charset=utf-8",
data: json,
success: function (results) {
}
});
If you want to do a PUT request you should use the method: 'PUT' as part of your $.ajax call:
$.ajax({
url: '/api/ProfileIDAPI?id=' + result.data[0].id,
method: 'PUT',
contentType: "application/json; charset=utf-8",
data: json,
success: function (results) {
}
});
Do you have it installed on IIS? In that case, you have to configure it to handle your "PUT" request.
Right click on your website in the sidebar and go to properties.
Go to the "Home Directory" Tab
In the "applications settings", click on the "configuration" button
In the "Applications configuration" Window, there should be a Mappings Tab
Simply choose which file extensions you want to have mapped (in my case i wanted ASP to map GET, PUT, POST & DELETE), comma delimited. And thats it, not even a restart required.
Hope this helps

How to send text like "<>" in parameter with $.ajax to server?

On client side i have form wich is send to server using $.ajax:
function showSearchResults(searchText, fromSuggestions) {
$.ajax({
url: "/Home/Search",
data: { searchText: searchText, fromSuggestions: fromSuggestions },
success: function (response) {
//processing response
},
beforeSend: function () {
showLoadingPane(); //function to show loading image
}
});
}
On server I have following code:
[HttpGet]
[AsyncAuthorize]
public ActionResult Search(string searchText, bool fromSuggestions = false)
{
//handling request
}
When I type in form text "<>", while debugging i see "<>" in js, but on server I am getting just empty string ""
I tried to use encodeURIComponent(searchText) which gives me string "%3C%3E", but on server i get "3C3E"
Question closed. We had custom model binder that was filtering some symbols.

Why does this call to my controller not work?

I have the following JavaScript code on my view in MVC4 project:
jQuery.ajax({
url: "/Object/GetMyObjects/",
data: {
__RequestVerificationToken: jQuery("input[name='__RequestVerificationToken']").val(),
},
type: "POST",
traditional: true
}).success(function (data) {
sfds = JSON.parse(data);
});
and the following method in ObjectController:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult GetMyObjects()
{
var sfds= _db.SFDS.ToList();
return View(sfds);
}
Why does the controller not get called when the JavaScript is run? Even when I remove the ValidateAntiForgereToken it does not work. In my console I see data returned is null.
I'm having a hard time getting some JSON on my view today.
You aren't returning JSon. You are returning (or attempting to return) a view. You need something like this, in your controller:
return Json(sfds, JsonRequestBehavior.AllowGet);
And, add this to your .ajax() properties:
dataType: "json",

MVC 4 APIController not receiving POST data

Sure this had been dealt with many times... but.. just cant see what im doing wrong!
This is a simple JS script that Posts data back to ApiController.
function WebCall(url,parameterObject, callBackFunction) {
this.callbackfunction = callBackFunction;
this.parameterObject = parameterObject;
this.url = url;
self = this;
this.GetData = function () {
//self = this;
$.ajax({
//dataType: "json",
type: "POST",
url: self.url,
data: JSON.stringify(self.parameterObject),
contentType: "application/json;charset=utf-8",
success: function (data) {
self.callbackfunction.call(this, data);
},//self.GotData,
error: function (xhRequest, ErrorText, thrownError)
{
alert("error : " + ErrorText)
},
complete: function () {},
})
}
}
The data being sent (parameterObject) is simply
var postData = {
clientId: id
}
The c# code in the controller is :
public class ClientPostObject
{
public string clientId;
}
public class ClientDetailController : ApiController
{
[HttpPost]
public ClientDetailWidgetData GetClient(ClientPostObject clientObject)
{
return new ClientModel().GetClientDetail(clientObject.clientId);
}
}
In Google chrome developer tools, the XHR is showinf 'form Data' as clientId:A0001 - so that looks ok?
No matter what I try (and I'be been through many suggestions on the web), the post data is not there.
Sure its something simple.... Thanks in advance.
Unless you're planning on using a full-on form to submit to this method at some other point, it doesn't really make sense to ask the model binder to attempt to bind to a complex type when you're just using one property. Change your method signature to:
[HttpPost]
public ClientDetailWidgetData GetClient(int clientId) // or whatever type clientId represents
{
return new ClientModel().GetClientDetail(clientId);
}
I'd also recommend adding Glimpse at some point (http://getglimpse.com/) so that you can see how the model binding and/or routing of your app works.
Try to ditch contentType and don't stringify data:
$.ajax({
type: "POST",
url: self.url,
data: self.parameterObject,
success: function (data) {...},
...
});

Categories

Resources