I'm having a problem with asp.net request validation. I have a basic page with a search field and a button. If the user inputs some illegal characters in the search field and clicks the button then of course I can validate his input in JS and everything's OK. However I have also a lot of LinkButtons not associated with the search functionality that do postbacks and when it happens I get the YSOD.
I know you can turn this feature off by adding ValidateRequest="false" in page directives or web.config, however I'd like to know if there is better and more elegant solution than simply disabling request validation completely.
Thanks.
you can use anti XSS Library to avoid cross scripting attack. check for this link AntiXSS asp.net .
and you can turn of the Yellowscreen of Death. by changing the CustomError mode to Remoteonly. so that remote user wont see the YSOD. only local server will see the YSOD
in web.config add line like this.
<configuration>
<system.web>
<customErrors defaultRedirect="yourErrorPage.html"
mode="RemoteOnly">
</customErrors>
</system.web>
</configuration>
Sounds to me like you need to put validation groups against your form elements (could be I'm misunderstanding the question).
(This would be easier if you'd have posted some code)
<asp:Panel runat="server" DefaultButton="btnSearch">
<asp:TextBox runat="server" ID="txtSearch" />
<asp:RequiredFieldValidator runat="server" ControlToValidate="txtSearch" ValidationGroup="vgSearch" ErrorMessage="Search is required!" />
<asp:Button runat="server" ID="btnSearch" ValidationGroup="vgSearch" Text="Search" />
</asp:Panel>
<asp:LinkButton runat="server" ID="btnLogin" Text="Login" ValidationGroup="vgLogin" />
<asp:LinkButton runat="server" ID="btnCakes" Text="Cakes!" ValidationGroup="vgCakes" />
Anyway, the idea is that your search form and associated validators have one validation group, and your other buttons have other validation groups, then the validator won't fire when you click another button.
I'm not actually sure if you NEED the validation groups against individual link buttons, I don't think you do, but I'm putting 'em in there to demonstrate my point.
If I've completely missed the boat, let me know :)
EDIT:
I should mention that I've just thrown the above code together, can't guarantee it's all formatted correctly, etc, etc.
Oddly enough, the day after I attempted to answer this, a co-worked asked me to help with the same problem, so here's what I'm up to so far...
(Bare in mind that while I've been developing in .Net for a number of years, I've never had need to delve that deeply into the page life cycle, ViewState or any of the hideously complicated bits that keep better dev's up at night)
Initially, I thought that overriding the PostBack event in JavaScript would allow me to edit the form post and remove the offending characters, so I tried it with a simple alert, but the potentially dangerous Request.Form was still appearing, so whatever's causing it is happening before the PostBack event is being fired.
So, after investigating the page life cycle, overriding every method I could and doing a whole lot of debugging, I found that the error is being throw in the DeterminePostBackMode method.
Now, by my understanding, this method looks at the form post and converts it to a NameValueCollection, so I built my own NameValueCollection, stripping out the "<" character (I only tested with that character to start with).
Protected Overrides Function DeterminePostBackMode() As System.Collections.Specialized.NameValueCollection
Dim stream As New System.IO.StreamReader(Request.InputStream)
Dim nvCollection As New System.Collections.Specialized.NameValueCollection()
Dim _split() As String = stream.ReadToEnd().Split("&")
If _split.Length > 1 Then
For i As Integer = 0 To _split.Length - 1
Dim kv() As String = _split(i).Split("=")
Dim _key As String = HttpUtility.UrlDecode(kv(0))
Dim _value As String = HttpUtility.UrlDecode(kv(1))
If _value.Contains("<") Then _value = ""
nvCollection.Add(_key, _value)
Next
End If
'For Each s As String In nvCollection
' Response.Write(String.Format("<p>{0}={1}</p>", s, nvCollection(s)))
'Next
Return nvCollection
End Function
And that worked brilliantly, the offending value was being stripped out and the NameValueCollection was being returned without causing an error...
Except I was still seeing the error message.
At the moment, I've tracked it to the PreInit page event, and I'm trying to figure a way around it, I'll update this as I make progress.
UPDATE:
I'm now fairly sure that the issue ISN'T with the values being stored in the ViewState. After reading this excellent article on ViewState, I tried setting the value of a TextBox to "<script" declaratively, which means it shouldn't be stored in the ViewState, which means that the error isn't caused by processing being carried out on the ViewState.
I think.
Related
If I have this asp.net button:
<asp:Button ID="Button_Save" Width="150px" OnClick="Button_Save_Click" runat="server" Text="Save" />
In order to prevent the user to press the button twice to insert two data records, I added this in the code behind:
Button_Save.Attributes.Add("onclick", "this.disabled='true';" + ClientScript.GetPostBackEventReference(Button_Save_Data, null) + ";");
It works fine with IE and Chrome. However, in Firefox, every time the user presses the button once, I got two data records inserted.
After some time googling, I modified the button this way by adding: UseSubmitBehavior="false":
<asp:Button ID="Button_Save" Width="150px" UseSubmitBehavior="false" OnClick="Button_Save_Click" runat="server" Text="Save" />
Then it also works with Firefox, only one data record inserted. But then I will have to add that setting for every button on my web application. It requires a lot of work.
However, I think this is really a big problem if that is the case always with asp.net app running on Firefox. Or did I implement something wrong?
Thanks in advance.
You would be better off adding checks to your SAVE code to prevent duplicate POSTs. I've used code like yours and still had duplicate records because someone hit the Refresh button at the wrong time.
EDIT:
Here is the code I use. Key is to match a value on the server with a value coming back in the postback.
In Page_Load:
If Not IsPostBack Then
Session("rcdupdate") = Server.UrlEncode(System.DateTime.Now.ToString)
End If
In Page_Prerender
ViewState("rcdupdate") = Session("rcdupdate")
And in the Save routine
If Session("rcdupdate").ToString = ViewState("rcdupdate").ToString Then
... write the data to the database ...
Session("rcdupdate") = Server.UrlEncode(System.DateTime.Now.ToString)
End If
You can extend asp:button and add your new functionality, then fine/replace all of your asp:buttons. Going forward you can then change all your buttons in once place.
So I haven't used ASP.NET for three years or so and I'm really rusty on it. My old code isn't available to me for review (at an old company). This question should be pretty basic, but I can't find any good or reliable or not-super-old resources on the issue, so I'm asking here.
Can I get a general overview of databinding again? I remember it being really useful for select boxes, etc., but I don't really remember how it works. Maybe a good ASP.NET tutorial in general, because I don't remember how it handles POST requests or anything like that really either. Should I just try ASP.NET MVC?
Relatedly, suppose I have a public variable in my codebehind page. Right now I am accessing it by saying Page.DataBind() at the end of the page load function and then running <%# variable %> in the ASPX, but that's not how I remember doing it before and I reckon that it's not very good practice. What's the best way to display variables from codebehind?
Databinding in general (at least in the WebForms model) is mostly a case of assigning fields to be displayed, setting the DataSource property to a suitable object that contains those fields e.g. a DataReader, DataTable, a Collection, and calling the DataBind method. So for your select case, you'd put an <asp:dropdownlist runat="server" id="MyDropDownList"> in the markup for the page, and then in the code
DataSet myDataSet;
myDataSet = someDataMethod();
MyDropDownList.DataTextField = fieldname;
MyDropDownList.DataValueField = fieldname;
MyDropDownList.DataSource = myDataSet;
MyDropDownList.DataBind();
Or you can avoid writing that kind of code and do it in the markup if you use a DataSource control e.g. <asp:SqlDataSource>, <asp:ObjectDataSource>
<asp:SqlDataSource runat="server" id="MySqlDataSource" ConnectionString="aConnectionString" SelectCommand="MyStoredProcName" SelectCommandType="StoredProcedure" />
<asp:dropdownlist runat="server" id="MyDropDownList" DataSourceId="MySqlDataSource" DataTextField="fieldname" DataValueField="fieldname">
For putting your variable on a page, the way you might have done it before is to have a label or textbox on the page, that in your code-behind you assign your variable to the Text property e.g.
<asp:label runat="server" id="MyLabel" />
MyLabel.Text = myVariable.ToString();
Postbacks: you can test the IsPostback property of a page in code-behind to determine if it's a postback or not. After the Page_Load method, other methods will fire if you've defined them e.g. SelectedIndexChanged for a DropDownList.
I really wanted to answer this question with examples and code etc.. but I would just be rehashing information that has been on the web for years and been explained in blogs and articles countless times. You can start with this article
which explains almost everything you need to know.
I have bolded the ones that I think are important to note that some my skim over.
<%# %> Syntax
Page.DataBind() versus Control.DataBind()
Data-bound list controls
Repeater control
DataList control
DataGrid control
Accessing data
DataSet class
DataReader class
Binding in list control templates
DataBinder.Eval method
Explicit casting
ItemDataBound event
As for learning MVC over webforms, that is whole different story. They both have pluses and minuses depending on your time, what you NEED to know and what portions of the project are important. Both techs can accomplish the same thing as they are all ASP.NET at their core, just different approaches so you will be fine either way.
Does asp.net have a built in mechanism that can sanitize all textbox input instead of redirecting to the error page?
I have a textbox input where a user can enter a name, but if they try to enter and <> tags the page automatically throws an error. I just want to handle this error in a user friendly way.
You'll want to look at the AntiXSS library for that. It's a dll so it's easy to drop in and start using it.
The download is at CodePlex.
You can use the ASP.NET RegularExpressionValidator control with a pattern like: ^[^<>]*$
<asp:RegularExpressionValidator ID="rev" runat="server"
ControlToValidate="txtBox"
ErrorMessage="The <> tags are not allowed!"
ValidationExpression="[^<>]*" />
<asp:RequiredFieldValidator ID="rfv" runat="server" ControlToValidate="txtBox"
ErrorMessage="Value can't be empty" />
The RequiredFieldValidator is used in conjunction with the RegularExpressionValidator to prevent blank entries. If that textbox is optional, and only needs to be validated when something is entered, then you don't have to use the RequiredFieldValidator.
The benefit of doing it this way is that the error can be handled gracefully and the user can be notified on the same page.
However, if you need to do this for many textboxes and you just want to present something nicer than the error page, you could handle the ValidateRequest error to provide a friendlier message and keep the user on the same page (not just replace it with a custom error page). For more info, check out Kirk Evans' post: Handling ValidateRequest errors within a Page (refer to the section titled Overriding the OnError Method).
Read this for a step-by-step: http://yourtahir.wordpress.com/2008/03/28/aspnet-not-allow-html-in-text-boxserver-error-in-application-a-potentialy-dangerous-requestform-value-was-detected/
You have to do some web.config work.
ASP.net has validation controls
[http://msdn.microsoft.com/en-us/library/7kh55542.aspx][1]
Also there is Mark Down Editor which is a control that strips out html tags etc.
Can anyone explain what might be causing this error. Im thinking its the quotes.
Exception Details: System.Web.HttpRequestValidationException: A potentially
dangerousRequest.Form value was detected from the client
(ctl00$ContentPlaceHolder1$DetailsView1$txtContent="...l economy.<br /><br />The
Prop...").
The contents of a control (probably a textbox) contains what ASP.net considers to be markup, eg:
<br /><br />
You can add ValidateRequest="false" to the Page directive in your .aspx file as follows:
<%# Page ........ ValidateRequest="false" ........ %>
As other answers noted, asp.net is doing this to try and protect you from potentially malicious input so make sure you're aware of the risk and encode/decode user data appropriately.
I think you can take a look at this A potentially dangerous Request.Form value was detected
Its the html "<br/>" tags.
Here's an article with a brief explanation . Also shows you how to work around it by turning off validation. Though I guess that would be a bit dangerous to just turn it off.
It actually should be
<br /><br />
it complains about.
That would be the '<' and '>'.
EDIT: It's assumed that including html entries in form responses is intended as an attack on the server on which the form resides. So, by default, any code that resembles html (i.e. includes '<' or '>') is automatically flagged as a problem.
One way to resolve this is to turn off this type of validation by setting validateRequest="false" in the Page directive for that page, but there are other (and better) ways to work around that.
Here's some information from Microsoft about this issue.
My idea: allow this exception to be thrown. Use Application_Error handler to write code, that redirects (using Response.Redirect - this is important, since this gives users’ browser ability to go back) user to a custom error page. On this page write some text explaining that users had incorrectly input some text. Something like:
"Dear user, you have entered some invalid text, like “<” or “.”. Please, enter text using only characters and numbers".
Put a link on that page, and this link can contain a javascript "back" command:
href="javascript: history.go(-1)"
Users after clicking suchlink will be redirected by their browsers to the previous page, where they can re-edit their input.
I have a question about what could stop a RequiredFieldValidator from preventing a postback.
I began working on an older, but simple aspx form and my predecessor used manual, server-side form validation (checking to see if some form fields have a value and if not displaying an error message in a label). I thought I'd clean out some unneeded code and replace the manual checking with RequiredFieldValidator controls, but while they appear to be validating, they aren't preventing a postback. Ie., I get my error messages displayed but the postback still occurs.
The form is quite simple and there are no CausesValidation="false" attributes set. My controls look like:
<asp:TextBox ID="txtPhone" Runat="server" Columns="20" MaxLength="20" />
<asp:RequiredFieldValidator ID="rfvPhone" runat="server" Display="Dynamic"
ErrorMessage="* Required" ControlToValidate="txtPhone" />
I created a brand new webform in the same project with just a single textbox, validator and submit button and it acts the same way. Error message displays but postback still occurs.
Is there a global or project-wide setting that would cause this behaviour? Something in the web.config or global.asax?
Whew. Okay, I found the problem, basically by creating a brand new project and comparing its web.config line-by-line with my old project. Turns out the culprit is this:
<xhtmlConformance mode="Legacy"/>
If I remove the line, my validation works the way I expected it to. Googling that uncovered a bunch of blog posts about how VisualStudio adds that line to the web.config when upgrading web apps from .net 1.1 to .net 3.5.
The blog posts were mainly complaining about how that field interferes with .net's AJAX stuff, but I'm guessing it messes with the JavaScript emitted for the RequiredFieldValidator in a similar fashion.
Validation can occur on the client if available, or on the server. The job of the validator isn't to prevent a postback, it's to validate the input.
Make sure that you have javascript enabled, and try explicitly setting "EnableClientScript" to true.
In the code-behind, you should never trust that the validators are validating on the client, and always use "if Page.IsValid".
I had the same problem, but the answer turned out to be quite different. I was also upgrading to .NET validation from server-side hard coded validation.
The issue in my case turned out to be related to the ASP.NET rewriting engine used from the MSDN article URL Rewriting in ASP.NET. Using the default implementation of the "Actionless Form" was the culprit - apparently this one was written based off of an earlier version of .NET and the JavaScript on the form that prevented the postback was not being send to the output because it was missing code.
Anyway, in case anyone else is using this rewriting engine, the solution was to change the default implementation of ActionlessForm to the following:
Public Class Form
Inherits System.Web.UI.HtmlControls.HtmlForm
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
MyBase.Render(New ActionlessFormHtmlTextWriter(writer))
End Sub
End Class
Public Class ActionlessFormHtmlTextWriter
Inherits HtmlTextWriter
Sub New(ByVal writer As HtmlTextWriter)
MyBase.New(writer)
Me.InnerWriter = writer.InnerWriter
End Sub
Sub New(ByVal writer As System.IO.TextWriter)
MyBase.New(writer)
MyBase.InnerWriter = writer
End Sub
Public Overrides Sub WriteAttribute(ByVal name As String, ByVal value As String, ByVal fEncode As Boolean)
Dim Context As HttpContext = HttpContext.Current
'Skip the action attribute of the form control.
If Not (name = "action") OrElse Not Context.Items("ActionAlreadyWritten") Is Nothing Then
MyBase.WriteAttribute(name, value, fEncode)
Else
Context.Items("ActionAlreadyWritten") = True
End If
End Sub
End Class
What this does is simply supress the action attribute, but allow any other logic in the framework to run. This should future proof this in case Microsoft decides to change the form again.
If you press "Enter" inside a textbox to submit the form, I don't think the validators will prevent the postback.
Could you try an explicit EnableClientScript="True" parameter to the RequiredFieldValidator?
I have found that this can sometimes also be caused by the unobtrusive validation mode first introduced in .NET 4.5 (Microsoft docs here). Especially when bringing legacy projects forward to a newer framework version.
Adding the below value in the configuration section of the project's web.config file fixed the issue for me:
<appSettings>
<add key="ValidationSettings:UnobtrusiveValidationMode" value="None" />
</appSettings>