ASP.NET MVC - A potentially dangerous Request.Form value was detected from the client - asp.net-mvc

Am trying to click save button to update what I have in text editor using ckeditor but I got this error
A potentially dangerous Request.Form value was detected from the client (OPTION_VALUE="Welcome to the Na...").
The controller is shown below
Controller
public ActionResult EditRegistrationGuideline(long id)
{
OPTIONS options = _optionsService.GetOption(id);
return View(options);
}
//
// POST: /Product/Edit/5
[HttpPost]
public ActionResult EditRegistrationGuideline(long id, OPTIONS options)
{
try
{
// TODO: Add update logic here
if (ModelState.IsValid)
{
options.OPTION_ID = id;
options.ACTION_STATUS = 0;
options.CREATED_DATE = DateTime.Now;
_optionsService.AddOption(options);
return RedirectToAction("Index");
}
}
catch
{
//return View();
ModelState.AddModelError("", "We cannot edit this Option. Verify your data entries !");
}
return View();
}
and the view is here
View
#{
//ViewBag.Title = "CreateRegistrationGuideline";
}
<div class="content-header clearfix">
<h1 class="pull-left">
<i class="fa fa-plus"> </i> Edit Registration Guideline
</h1>
<div class="col-xs-3 pull-right">
<input type="button" class="btn btn-block btn-warning" value="Back" onclick="location.href='#Url.Action("IndexRegistrationGuideline", "Options")'" />
</div>
<div class=" box box-body box-primary">
#using (Html.BeginForm("EditRegistrationGuideline", "Options", FormMethod.Post, new { #class = "form-horizontal", #enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#*<h4>OPTIONS</h4>
<hr />*#
#*#Html.ValidationSummary(true)*#
#Html.ValidationSummary(false, null, new { #class = "text-danger" })
<div class="row .col">
<div style="margin-top:20px" class="mainbox col-md-12 col-md-offset-0 col-sm-8 col-sm-offset-2">
<div class="panel panel-info">
<div class="panel-heading">
<div class="panel-title">Edit Option</div>
</div>
<div class="panel-body">
#*<div class="form-group">
#Html.LabelFor(model => model.OPTION_NAME, new { #class = "control-label col-md-2" })
<div class="col-md-10">*#
#*#Html.LabelFor(model => model.OPTION_NAME, new { #class = "control-label col-md-2" })
<div class="col-md-10">*#
#*#Html.EditorFor(model => model.OPTION_NAME)*#
#*#Html.HiddenFor(model => model.faculty_activation_date, new { #Value = System.DateTime.Now })*#
#Html.HiddenFor(model => model.OPTION_NAME)
#Html.ValidationMessageFor(model => model.OPTION_NAME)
<div class="form-group">
#*#Html.LabelFor(model => model.OPTION_VALUE, new { #class = "control-label col-md-2" })*#
<div class="col-md-10">
#Html.LabelFor(model => model.OPTION_VALUE, "Option Value")
#*<textarea class="form-control" placeholder="Enter Option Value" name="OPTION_VALUE" id="editor1"></textarea>*#
#Html.TextAreaFor(model => model.OPTION_VALUE, new { #class = "form-control", #id = "editor1" })
#Html.ValidationMessageFor(model => model.OPTION_VALUE, "", new { #class = "text-danger" })
</div>
</div>
#*<div>
#Html.LabelFor(model => model.OPTION_VALUE, "Option Value")
#Html.TextAreaFor(model => model.OPTION_VALUE, new { #type = "textarea", #id="editor1", #class = "form-control", #placeholder = "Enter Option Value", #autocomplete = "on" })
#Html.ValidationMessageFor(model => model.OPTION_VALUE, null, new { #class = "text-danger" })
</div>*#
#*<div class="form-group">
#Html.LabelFor(model => model.ACTION_STATUS, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.ACTION_STATUS)
#Html.ValidationMessageFor(model => model.ACTION_STATUS)
</div>
</div>*#
</div>
<div class="panel-footer">
<div class="panel-title">
<div class="form-actions no-color">
<input type="submit" value="Save" class="btn btn-success" />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
}
#*<div>
#Html.ActionLink("Back to List", "Index")
</div>*#
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script src="~/Scripts/jquery-3.1.1.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
<script src="https://cdn.ckeditor.com/4.5.7/standard/ckeditor.js"></script>
<script>
$(function () {
CKEDITOR.replace('editor1');
});
</script>
}
Please what do I do.
I use CKEDITOR

XSS error ("A potentially dangerous Request.Form value was detected from the client(...)").
Solution:
[ValidateInput(false)]
Differnce b/w them
AllowHtml:
The AllowHtml attribute can be applied to a Model property and it will disable the validation by ASP.Net MVC only for that particular property
Advantages
The AllowHtml attribute is developed for Model class.
The Scope is limited to specific property of the Model class.
It is the safe and recommended solution.
ValidateInput
The ValidateInput attribute can be applied to a Controller’s Action method and it will disable the validation by ASP.Net MVC only for that particular Action method.
Advantages
The Scope is limited to specific Action method of the Controller class.
If you have multiple properties accepting HTML content, then this method will reduce redundancy.
When Model class is not used for designing Form elements then this attribute is needed.For complete details Link

Just place ValidateInput(false) attribute on controller's action.
[HttpPost]
[ValidateInput(false)]
public ActionResult EditRegistrationGuideline(long id, OPTIONS options)
The other option is to place [AllowHtml] attribute on Model Property, have a look on SO post to get difference between them
ValidateInput(false) vs AllowHtml

I was experiencing a similar issue with the following error message A potentially dangerous Request.Form value was detected from the client.
As an alternative to the previous answers, I found encoding the value passed back to the controller worked. CKEditor allows you to do this by setting the config config.htmlEncodeOutput = true;.
The documentation for this can be found at: https://docs-old.ckeditor.com/ckeditor_api/symbols/CKEDITOR.config.html#.htmlEncodeOutput

I got this error while testing XSS on my site.
This is a very good feature that the model gives us that prevents XSS, CSRF from penetrating your site.
Do not disable it as much as possible.

Related

Using MVC HtmlHelpers, how to send a form with a value from database along with User-filled values?

I'm trying to write a Bank Application. In the Transaction Page, I want to take the value of CheckingAccountId from the User Accounts Database (User.Identity.GetUserId()). But, how should I assign the value of User.Identity.GetUserId() to CheckingAccountId. This is the relevant Razor View Page Code:
using (Html.BeginForm("Deposit", "Transaction", FormMethod.Post, new {
#class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken();
<h4>Deposit Section</h4>
<hr />
#Html.ValidationSummary("", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(m => m.Id, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Id, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.TransactionAmount, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.TransactionAmount, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.CheckingAccountId, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#{
var userName = User.Identity.GetUserName();
}
#*THIS IS THE BEST I COULD DO. I NEED HELP HERE*#
#*#m.CheckingAccountId = userName*#
#Html.DisplayName(userName)**
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-default" value="Deposit" />
</div>
</div>
UPDATE:
I just found out that we can achieve this by adding the same in the ConnectionString when writing the SQL Query for pushing the transaction into the database. The solution would look something like this:
INSERT INTO table ( checkingaccountid, model_data ) VALUES ( $id, $data );
But I would still like to know if it's possible to send this id from the form when submitted along with the other data.

Refresh DIV using partial view in MVC5

I am trying to refresh a div based on the dropdown selection. I have a main view which uses a partial view (_Module). The main view has a dropdown; upon selecting the dropdown I am trying to change the content in the partial view which in turn would be reflected on the main view.
The main view:
#model Test.Models.CreateDirectoryModel
#{
ViewBag.Title = "CreateAdmin";
}
#using (Html.BeginForm("CreateAdmin", "RDBWeb", FormMethod.Post))
{
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#ProductType").change(function () {
var catType = $(this).val();
$("#result").load('#(Url.Action("GetPPOFlag", "RDBWeb", null, Request.Url.Scheme))?catType=' + catType);
});
});
</script>
#Html.ValidationSummary(true)
<div class="form-horizontal">
<h4>Create a New Directory</h4>
<hr />
<div class="form-group">
#Html.LabelFor(model => model.DirectoryNumber, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DirectoryNumber)
#Html.ValidationMessageFor(model => model.DirectoryNumber)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.ProductType, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.ProductType, new SelectList(Model.ProductType), "Select Product")
#Html.ValidationMessageFor(model => model.ProductType)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.DirectoryName, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.DirectoryName)
#Html.ValidationMessageFor(model => model.DirectoryName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.AdminName, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownListFor(model => model.AdminName, ViewBag.Drop as SelectList, "Select Admin")
#Html.ValidationMessageFor(model => model.AdminName)
</div>
</div>
<div id="result">
#if(Model.Module != null)
{
{Html.RenderPartial("_Module", Model.Module);}
}
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
<div>
</div>
</div>
}
The partial view is:
#model Test.Models.CreateDirectoryModel
#foreach (string s in Model.Module)
{
#Html.LabelFor(a => s.ToString());
}
The methods relevant for these in the controller are:
public ActionResult GetPPOFlag(string catType)
{
ProdTypeModel p1 = new ProdTypeModel();
int flag = p1.GetPPOFlag(catType);
return RedirectToAction("GetModule", new { flag = flag });
}
[HttpGet]
public ActionResult GetModule(int flag)
{
ModuleType m1 = new ModuleType();
List<string> moduleList= m1.GetModules(flag);
return PartialView("_Module", moduleList);
}
My problem is that by default the Partial view object is null initially as the dropdown value is yet to be chosen. I added a check to render the partial view only if the object is not null; but that does not load the new values into the partial view. All I see is that the GetModule method is invoked and the partial view method is called as well, but there is no change in the div on the main page nor the partial view.
try to do like this, just keep an empty div inside in the main view like this
<div id="result">
</div>
On dropdown selection change, give a ajax call and get partial view and render html in the div
$('#result').empty();
$("#result").html(data);

ASP MVC jquery validation in bootsrap tabs causes an undesired postback

I have a form with 3 bootstrap tabs in it. Client Validation works correctly when the tab where the validation error occurs is open and submit button is clicked. However, when i switch to a tab with no errors (while having errors in other tabs) a post back occurs and i get the correct validation messages.
Its a minor issue, but post back is not desired in this situation, because full client side validation must be completed before sending request to the server.
How can i correct this behavior?
Below is a copy of my form HTML:
#model RBZPOSMVC.ViewModel.CreateEditItem
....
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<ul class="nav nav-tabs">
<li class="active"><a data-toggle="tab" href="#Details">Item Details</a></li>
<li><a data-toggle="tab" href="#Sales">Sale Price Groups</a></li>
<li><a data-toggle="tab" href="#Purchases">Purchase Price Groups</a></li>
</ul>
<div class="tab-content">
<div id="Details" class="tab-pane fade in active">
<div class="form-group">
#Html.LabelFor(model => model.Item.ItemCode, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Item.ItemCode, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Item.ItemCode, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Item.ItemName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Item.ItemName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Item.ItemName, "", new { #class = "text-danger" })
</div>
</div>
.... // more form controls
</div>
<div class="hidden">
#for (var i = 0; i < Model.PriceGroupList.Count; i++)
{
<div class="form-group" id="#Model.PriceGroupList[i].PriceGroupTypeId">
#Html.HiddenFor(model => model.PriceGroupList[i].PriceGroupId)
#Html.LabelFor(model => model.PriceGroupList[i].PriceGroupName,
Model.PriceGroupList[i].PriceGroupName,
htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PriceGroupList[i].Price, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PriceGroupList[i].Price, "", new { #class = "text-danger" })
</div>
</div>
}
</div>
<div id="Sales" class="tab-pane fade in ">
</div>
<div id="Purchases" class="tab-pane fade in ">
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
<script>
$.validator.setDefaults({
ignore: ""
});
</script>
#Scripts.Render("~/bundles/items")
#Scripts.Render("~/bundles/jqueryval")
}
Since two of you tabs are hidden when you submit the form, you need to configure the $.validator to validate hidden elements (which are not validated by default).
You current use of $.validator.setDefaults({ ignore: "" }); is not correct for jquery version 2.2.0 (I believe that usage was depreciated in version 1.9) and it needs to be
$.validator.setDefaults({
ignore: []
});
Note: do not add the above inside $(document).ready()

#Html.CheckboxFor not displaying in mvc

The checkbox is not displaying in page. I tried many solutions in google. Nothing worked. Here s the code:
#model project.gamestatus
#using (Html.BeginForm("Create", "Calculator", FormMethod.Post, new { id = "frmID" }))
{
//other codes
<div class="form-group">
#Html.Label("Show on Screen", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.CheckBoxFor(m => m.display_status)
#Html.ValidationMessageFor(model => model.display_status, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-info" />
</div>
</div>
}
Only if the checkbox is shown in page i can proceed with validation. In my view there is no checkbox
First of all, you need to ensure that the display_status model is of boolean type and assigned the display name to it along with any validation.
[Display(Name="CheckBox Display Name")]
[Required]
public bool display_status { get; set; }
Also, #Html.CheckBoxFor do not support the label of checkbox. Therefore, you can have the label of the checkbox using #Html.LabelFor as follow:
<div class="form-group">
#Html.Label("Show on Screen", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.CheckBoxFor(m => m.display_status)
#Html.LabelFor(m => m.display_status)
#Html.ValidationMessageFor(m => m.display_status, "", new { #class = "text-danger" })
</div>
</div>
though its a very old post but I undergo this issue todat, but when I inspected I found that the CSS property opacity was set to 0 so changing it to 1 will solve the issue
#Html.EditorFor(model => model.Active, new { htmlAttributes = new { style = "opacity: 1" } })
I fixed the problem by setting the height to 20px explicitly. When I examined the page, it was being set to 20%:
#Html.CheckBoxFor(m => m.ExistingUser, new { style="height:20px" })

How do I post varied length list to controller?

MVC4. I have a dynamic list on a view, a new textbox is added with button click (which adds a partialView) so user can enter a list of stuff. That is contained in a form element with a submit button.
In the controller I have tried three different types:
[HttpPost]
public ActionResult Index(IEnumerable<AccessoryVM> form)
{
-- form is NULL
[HttpPost]
public ActionResult Index(AccessoryVM form)
{
-- form has only the first item in the list
[HttpPost]
public ActionResult Index(FormCollection form)
{
-- seems to receive the list, but having trouble getting the values
All the examples I have seen are using a for list to add an index to each item, but they aren't using a dynamic list (it has a fixed length).
What should the Controller receiving type be?
EDIT to add more detail:
Button click appends partial view:
$("#add-item").on("click", function () {
$.ajax({
url: '/Accessory/AddItem',
cache: false,
success: function (html) {
$("#form-body").append(html);
}
})
return false;
})
Partial View:
#model EmployeeHardwareRequest.Models.ViewModels.AccessoryVM
<div class="form-group col-md-3">
#Html.LabelFor(model => model.ItemDescription, htmlAttributes: new { #class = "control-label" })
<div>
#Html.DropDownListFor(model => model.AccessoryId, Model.AccessoryDdl, new { #class = "form-control" })
</div>
</div>
<div class="form-group col-md-9">
#Html.LabelFor(model => model.ProductLink, htmlAttributes: new { #class = "control-label" })
<div>
#Html.EditorFor(model => model.ProductLink, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ProductLink, "", new { #class = "text-danger" })
</div>
</div>
Main View - partial is appended to the #form-body:
#using (Html.BeginForm("Index", "Accessory", FormMethod.Post, new { #id="accessory-form", #class = "form-horizontal" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div id="form-body">
<div class="form-group col-md-3">
#Html.LabelFor(model => model.ItemDescription, htmlAttributes: new { #class = "control-label" })
<div>
#Html.DropDownListFor(model => model.SelectedAccessory, Model.AccessoryDdl, new { #class = "form-control" })
</div>
</div>
<div class="form-group col-md-9">
#Html.LabelFor(model => model.ProductLink, htmlAttributes: new { #class = "control-label" })
<div>
#Html.EditorFor(model => model.ProductLink, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ProductLink, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<button id="add-item" class="btn btn-primary">Add Another Item</button>
</div>
<div class="col-md-6">
<input type="submit" value="Select Software" class="btn btn-default pull-right" />
</div>
</div>
}
Most likely, you have a binding issue. Assuming all you're posting is a collection of AccessoryVM, then the parameter should be List<AccessoryVM> form. However, in order for the modelbinder properly bind the posted values, your input names must be in a specific format, namely either form[N].Foo or just [N].Foo.
You haven't given any detail about what's going on in your view, but since these are dynamically added, you must be using JavaScript to add additional inputs to the page. If you're doing it via AJAX (returning a partial view), you'll need to pass the index to your endpoint so that it can be utilized to generate the right input names. If you're using something like Knockout, Angular, etc., you should ensure that whatever template is being used to generate the inputs takes an index into account.

Resources