Potentially dangerous Request.QueryString value was detected from the client - c#

So, I know WHY this happens but just unsure the best way to go about fixing it.
The application I am using has a ViewModel and binds/maps the properties from a Model.
This VM is then bound to the View and using the #Html.TextBox() helper.
This is an example: The actual text value from the DB is:
"Université de Montréal"
The rendered output on the HTML in the DOM is:
<input class="validate" id="EmployerName" name="EmployerName" type="text" value="Universit&#233; de Montr&#233;al" />
Now, once the page has been loaded, it does an AJAX GET call by serializing the form and sending that across.
At this point, it DOES hit the controller (because I have the [ValidateRequest(false)] attribute applied to that controller action, but I then get the error:
A potentially dangerous Request.QueryString value was detected from the client (employername="Université de Montr&#233...").
At this point, I am stuck as to what to do to fix the problem and let the request process normally.
I know by adding the in the web.config fixes it, I do not want to change it site wide.
any ideas the best thing to do to allow this request to process as normal?
Controller action:
[ValidateInput(false)]
[OutputCache(NoStore = true, Duration = 0)]
public ActionResult GetMoreData(Criteria crit)
{
...
}

So, I managed to fixed this.
When using the MVC TextBoxFor, it automatically encoded the string (which is nice).
Adding the [ValidateInput(false)] attribute to the controller action works to the point where it can call the action method. I then simply did an HtmlDecode ON SAVE. On load, I simply HtmlEncode the string.
Not the best solution if you have a lot of properties being displayed to the user but it works.

Related

Onclick action doesnt go to the method

here is the code from my cshtml file
<button type="button" class="button js-book-class" onclick="#Url.Action("BookTheClass", "MemberArea", new { ClassID = Aclass.ClassID })">Book Now</button>
and here my function inside MemberAreaController.cs
[HttpPost]
public ContentResult BookTheClass(int ClassID)
{
Class selectedClass= _context.classes.Find(ClassID);
selectedClass.spaceUsed++;
_context.SaveChanges();
return Content(ClassID.ToString());//just for testing
}
This is because you have conflict.
Url.Action generates a href link, which in click, will execute a browser navigation, which means GET request.
While your server BookTheClass action is expected to be called when executing a POST.
The easy fix which in this case is also the not so good solution, is to change your method to [HttpGet] (which i believe is the default) and it will be resolved.
The more accurate solution, will be to create a form element and making the button submit the data, this will acquire you a change only in HTML and not server side.
The reason i think you should stick to Post, is because i believe in the notion that GET should be consider as a query like, and that identical requests should have the same response.
Whereas Post should have the role of Actions which result in side-effects. which in Rest, means Creation. But as general rule of changing a state in the server as a result.

How should a refresh be handled after a redirect on ModelState failure using the strict PRG pattern?

So I've always used the loose PRG pattern where you return a view on ModelState validation failure from a POST action. However, it's always bothered me that I have to build the model not only in the GET action, but also rebuild it again in the POST action on failure. I've used different methods of doing the rebuilding using "view model builders" or just a private function within the controller that builds the view model for both actions, but these still bother me as well.
After reading this article by Ben Foster (http://benfoster.io/blog/automatic-modelstate-validation-in-aspnet-mvc), it makes a lot more sense to just rely on the GET action to build your view model - keeping it one area of the code - and then use the necessary action filters to save the ModelState for rendering when you are redirected back to GET on a failed POST.
So I've implemented that using the filters Ben mentions in his article like below. However, I am curious what happens if the user refreshes after they have been redirected back to the GET on a ModelState failure? How would I differentiate between someone accessing the GET directly versus a ModelState failure? Currently the ModelState would be gone if a user refreshes at that point. Is that the correct action, or should the user continue to see the errors until they POST with valid data? Essentially, should they be seeing the data that is in the database, or should they continue to see the changes they made when POSTing?
[ImportModelStateFromTempData]
public ActionResult Edit(int id)
{
// in a real application this would be retrieved from the db
var editView = new EditView()
{
UserId = id,
Name = "John Doe",
Age = 20,
Message = "Hello world"
};
return View(editView);
}
[HttpPost]
[ValidateModelState]
public ActionResult Edit(EditCommand editCommand)
{
// save to db here in real application
return RedirectToAction("Success");
}
I use the same [ImportModelStateFromTempData] filter in a couple projects, and it works great.
In my opinion, if the user refreshes, you shouldn't preserve any model state errors. The user is asking for a fresh view of that page, and it'd be frustrating to never be able to get a clean view. In same vain that refreshing after a POST shouldn't resubmit a form, refreshing after a GET shouldn't preserve a POST.

Action method was not found on controller

Despite a ton of questions similar to this one, none seem relevant, so
I have an action with this signature
[HttpPost]
public ActionResult SaveOrder(PizzaOrder pizza, Guid? id){
...
}
I am trying to submit a form with a button. I have verified that the button sends a POST to
https://my/controller/url/SaveOrder?id=...
It also appears that the PizzaOrder data is being posted correctly.
But, my action never gets hit. Instead, MVC throws an exception
A public action method 'SaveOrder' was not found on controller
'Controllers.PizzaController'.
Why?
POST does not send form data in the URL querystring.
There can only be one cause and that's exactly what its saying. The url is wrong. To test this, use the browser developer tools and check to see what the url the page is posting to and what the actual url is. Controller vs PizzaController? or.... you are doing a GET to a POST. POST doesn't have SaveOrder?id=.
The request you are trying is GET not POST as you are passing parameters with Querystring ?id=... Try after removing [HttpPost] attribute

Adding HttpPost getting error 'The Resource Cannot Be Found' in MVC

I'm getting the error
Server Error in '/' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /ClientEdit/ClientEdit/1104
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.272
when I add HttpPost attribute to a controller. I've looked into this and corrected my code with posted(no pun intended) answers but nothing I've tried works. Here's my controller header:
[HttpPost]
public ActionResult ClientEdit(int id,FormCollection formCollection)
I added HttpPost so I can populate my FormCollection object. As with other SO posts, this causes the error. Removing it solves the issue but my FormCollection doesn't populate any key/value pairs.
My view has its form tag's method set to POST which solved other dev's issues but it doesn't solve mine. I tried adding 'name=' properties to my textbox controls as well as 'id=' but that doesn't work either.
<body>
<form method="post" action="1104" id="form1">
I don't know what else to try.
You need to provide you view that renders the <form> as well. The action on what you show as your HTML looks wrong to me. I would think it would be something like action="/Controller/ClientEdit".
you have given wrong value in the attribute action="1104".
Either you can specify proper route in action attribute or leave it if the route is same as of get.
This should work if GET and POST route are same
<form method="post" id="form1">
.....
</form>
use this:
#using(Html.BeginForm()){
<!--Your form field-->
}
Basically what is happening is that your action attribute is just pointing to the Id you have and not the url to post to.
You can do it manually like this:
<form action="ClientEdit/ClientEdit/1104>
<!--form fields-->
</form>
Yes, you are all correct. I was passing a userid as the action. This was legacy code that 'worked' for another feature but doesn't conform to the MVC pattern. I did some other research (as I'm not too familiar with MVC either) and started again from scratch using MVC as it should be. Thanks everyone.

MVC Form Submit - Redirecting to an action that is not accessible from the browser directly

I am learning MVC 3 after hours right now and last night I ran into an issue that seems like it would be very simple to solve but I can't seem to locate a solution for it.
I have a simple contact form. The end user fills out the form and submits it. When they submit the form I redirect the end user to a different action in the same controller which renders an "inquiry submitted" page/view which is basically a "Thank you page".
The controller is setup like so.
public ActionResult ContactUs()
{
return View();
}
[HttpPost]
public ActionResult ContactUs(ContactInfo contactInfo)
{
if (!ModelState.IsValid)
{
return View();
}
//perform some business logic
return RedirectToAction("InquirySubmitted",contactInfo);
}
public ActionResult InquirySubmitted(ContactInfo contactInfo)
{
return View(contactInfo);
}
The problem:
I do not want end users navigating directly to the InquirySubmitted action via the browser.
I only want the ContactUs action in the controller to be able to send users to the InquirySubmitted View.
I have attempted to make the InquirySubmitted action private so that only the controller can call it like so:
private ActionResult InquirySubmitted(ContactInfo contactInfo)
But this produces an error which I fully understand because I am forcing the browser to request InquirySubmitted by using RedirectToAction().
So my question is simply: What is the best "MVC 3 style" solution to this issue.
You will need to put logic in your InquirySubmitted ActionResult in order to prevent users from viewing the page if they are not supposed to.
You are already passing the InquirySubmitted method your model (ContactInfo). Could you simply inspect the data passed to the method and if it is absent then redirect the user to an error page (or some other page of your choice)?
An alternate solution would be to set a boolean in session that indicates that the user completed the "ContactUs" form. Then you could check for that session object within InquirySubmitted.
First, I would have to say.. Who cares if someone can navigate directly to the Inquiry submitted page? Is there any confidential information, or something sensitive there? If not, so what? What does it hurt?
However, if you're determined to do so. The answer to your question of "How to make an action not accessible directly from the browser" is that You can simply use Html.Action() to render the page, and then decorate the action method with a [ChildActionOnly] attribute.
This doesn't actually solve the problem though, since making the action indirectly accessible only answers your question, not solves your problem. Ultimately, you need to redirect the user to a url to load the page, so you will need some logic that determines if they can view the page or not. This is
Not sure if this still applies in MVC3, but in MVC2 it worked.
your global.asax file has your url structuring in it. You can add your InquirySubmitted to the list of urls that isn't accessible there.

Categories