I've got an ASP.NET 4 site on which I want to allow people to put '<' in their password. However, .NET gets in the way by blocking (what it sees as) an attempt to put HTML in a form field. I know I can turn off input validation entirely, but I only want to turn it off for this one field. Does anyone know an easy way to do that?
This is now possible with .NET 4.5.
Update your Web.config:
<httpRuntime targetFramework="4.5" requestValidationMode="4.5" />
Then set ValidateRequestMode="Disabled" on your password controls:
<asp:YourControl id="YourControl" runat="server" ValidateRequestMode="Disabled"/>
Note - after updating web.config, you might run into the error WebForms UnobtrusiveValidationMode requires a ScriptResourceMapping for 'jquery'. See ASP.Net 2012 Unobtrusive Validation with jQuery for more info on that.
More info on RequestValidationMode 4.5: requestValidationMode 4.5 vs 2.0
You can only turn off input validation for the entire page. The only solution I can think of is to turn off the input validation, and then scrub all the other (non-password) input fields using something like Anti-XSS.
You can turn input validation off for the single MVC action using the ValidateInputAttribute. Since you're only accepting username/password (I would assume) you should be able to scrub input yourself of any invalid characters. Use the Microsoft Web Protection Library to do that.
Note in ASP.NET 4 and higher to get ValidateRequest in the #Page directive to work you need to add <httpRuntime requestValidationMode="2.0" /> to web.config. See this page for details:
http://www.asp.net/whitepapers/aspnet4/breaking-changes
But this is my preferred approach:
namespace Controls
{
public class HtmlTextBox : TextBox
{
protected override bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
{
bool res = base.LoadPostData(postDataKey, postCollection);
Text = Text.Replace("<", "<").Replace(">", ">").Replace("&", "&");
return res;
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
ScriptManager.RegisterOnSubmitStatement(this, this.GetType(), "htmlTextBox" + UniqueID, "try { var item = document.getElementsByName('" + UniqueID + "')[0]; item.value = item.value.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); } catch (err) {}");
}
}
}
And then register the control in web.config:
<system.web>
<pages>
<controls>
<add tagPrefix="uc1" namespace="Controls" />
</controls>
</pages>
</system.web>
This way you can just use <uc1:HtmlTextBox runat="server" /> if you want to allow the textbox to post html, but other controls on the page will still be blocked from posting html unlike the approach of turning ValidateRequest off.
This is possible. Just add [AllowHtml] on the property that should not be validated.
see ValidateInputAttribute does not contain a definition for Exclude
Related
I'm using ASP.Net for web development. I've situation here. say I've many HTML/ASP.Net controls on my page, and I've to set visibility of each control based on Logged-in user's role. for this I'm doing as follows:
Storing each Function-Name and Role combination is DB
During render, checking for role permission for each HTML/ASP.Net control.
e.g: Displaying something like this:
<asp:Label runat="server" id="Lbl1" visible='<%=CheckVisibility("Display","Admin")%>'>
public bool CheckVisibility(string FunctionName, string RoleName){
// checks for db entry and returns bool value
}
Problem is, I've to do this for all the Controls. Is there any other optimized approach available to do this? please help me
Given only your description of what you're trying to solve, I would suggest you create your own controls which inherit from the built-in ones and add some properties to them. Then the controls can do the visibility check themselves. Something like
namespace StackOverflowTest
{
public class Label : System.Web.UI.WebControls.Label
{
public string DisplayRoles { get; set; }
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
Visible = PermissionHelper.CheckPermission("Display", DisplayRoles.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries));
}
}
public static class PermissionHelper
{
public static bool CheckPermission(string function, string[] allowedRoles)
{
// TODO: hit some sort of cache, so you don't make a bajillion queries to the DB
return true;
}
}
}
And then if you put this in your web.config (sorry, can't figure out how to do proper XML formatting here): <system.web>
<pages>
<controls>
<add tagPrefix="sot" assembly="StackOverflowTest" namespace="StackOverflowTest"/>
</controls>
</pages>
</system.web>
You can add this to your markup:
<sot:Label ID="AdminLabel" runat="server" Text="Bind this in OnLoad/!IsPostback or something" DisplayRoles="Admin,Management" />
This is just one of the many ways you can do this. It all depends on the requirements, of course. But I'm pretty sure you'll need your own classes for controls to have the possibility of making it manageable.
C# code:
public enum previlageType
{
superAdminPrevilages=1,
partnerPrevilages = 2,
dealerPrevilages = 3,
customerPrevilages=4
}
if ((previlageType)Enum.Parse(typeof(previlageType), Session["previlageType"].ToString())== previlageType.partnerPrevilages)
{
accordion.Visible = false;
}
ASP code:
<div id="accordion" runat="server">
Hello World, I'l be Hidden if a person with partner previlages is logged in. BUt will be visible if superadmin or any person except Partner logs in.
</div>
Hope it helps
If you're using a master page, you could get all the child page controls on load (get contentplaceholders, then get contentplaceholder controls).
Then when you have all the control names, do a lookup on your table and set its visibility to false if needed.
(below is vb but the translation should be easy.)
For Each cp As String In Me.ContentPlaceHolders
For Each ctl As Control In Me.FindControl(cp).Controls
If adminonly.Contains(ctl.ID) Then
ctl.Visible = False
End If
Next
Next
I might be completely off track by now, so I will just ask this here so someone can help me.
What I want to do, is to insert a value from my web.config, stored in an applicationSettings area, into my aspx markup. Specifically I want to reade a URL from config. This is the configSection setup I use
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=123456">
<section name="MyApp.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=12345" requirePermission="false" />
</configSections>
Later in that file are the actual settings like so:
<applicationSettings>
<MyApp.Properties.Settings>
<setting name="ImagesUrl" serializeAs="String">
<value>http://resources/images/</value>
</setting>
Now I want to reference the above value in markup like this:
<asp:Image ID="Image1" runat="server" ImageUrl="<%$AppSettings:ImagesUrl%>/Image1.jpg
I know there's an expression available <%$ AppSettings: ImagesUrl %>, but I'm not using the appsettings part of web.config, rather the configSection.
EDIT:
I believe I can only do it with ExpressionBuilder, because I have to concatenate the string with the individual image name. I changed the example above to reflect that.
I like Bert Smith Code Solution below for accessing the config section, only I need to put it in an expression builder.
I'm stuck at overriding the GetCodeExpression method from where I would call the Configuration Manager, but I don't understand how to build an expression the parameters.
public class SettingsExpressionBuilder: ExpressionBuilder
{
public override CodeExpression GetCodeExpression(BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context)
{
return ??
}
EDIT
The result looks like this, and works for all kinds of files, not just images:
<asp:ScriptReference Path='<%$Code:GetAppSetting("ResourcesUrl","JS/jquery/jquery.jqplot.js")%>'
and I simply used the example from Microsoft to return any kind of code from the expression builder:
return new CodeSnippetExpression(entry.Expression);
And GetAppSetting is a method in my custom Page class.
Typically you would create a custom settings class to read these values out as this artical describes. Personally, I would just use the appSettings as suggested above as this is existing functionality and for what your doing would on the surface seem adequate.
However, not knowing your circumstances, what your attempting to do could be solved without the custom settings like so:
In the code behind I created a protected function to retrieve the setting
protected string GetCustomSetting(string Section, string Setting)
{
var config = ConfigurationManager.GetSection(Section);
if (config != null)
return ((ClientSettingsSection)config).Settings.Get(Setting).Value.ValueXml.InnerText;
return string.Empty;
}
Then in the aspx markup I call this function
<div>
<label runat="server" id="label"><%=GetCustomSetting("applicationSettings/MyApp.Properties.Settings", "ImagesUrl") %></label>
</div>
Hope this helps.
Follow Up:
The CodeExpression will look something like this:
public override CodeExpression GetCodeExpression(BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context)
{
var config = ConfigurationManager.GetSection("applicationSettings/MyApp.Properties.Settings");
return new CodePrimitiveExpression(((ClientSettingsSection)config).Settings.Get(entry.Expression).Value.ValueXml.InnerText);
}
In my Test, I created a class called CustomSettingsExpressionBuilder and added it to the App_Code folder. Added the configuration for the custom express to the web.config and called it from aspx like so:
<asp:Label ID="Label1" runat="server" Text="<%$CustomSettings:ImagesUrl %>"></asp:Label>
Does it has to be in markup? Why don't you set it in code-behind.
Image1.ImageUrl= //fetch your settings here.
One another way would be defining a property or static method in your code-behind and then using that in the markup.
I'm not sure about the ASP.NET bit of it, but if this was normal code you'd do MyApp.Properties.Settings.Default.ImagesUrl, so try
<asp:Image ID="Image1" runat="server"
ImageUrl="<%$MyApp.Properties.Settings.Default.ImagesUrl%>
It would definitely be easier to store this in <appSettings> though.
I have a project and I am trying to register a custom server control (there is no .ascx file) on the page. I am currently using
Class Declaration
namespace MyApp.Controls{
public class CustomControl: WebControl{
public string Text
{
get
{
String s = (String)ViewState["Text"];
return ((s == null) ? String.Empty : s);
}
set
{
ViewState["Text"] = value;
}
}
protected override void RenderContents(HtmlTextWriter output)
{
output.Write(Text);
}
}
}
On my page,
<%# Register TagPrefix="myControls" Namespace="MyApp.Controls" %>
<myControls:CustomControl runat="server" Text="What up!" />
I receive a Parser Error, with the message "Unknown server tag 'myControls:CustomControl'."
What am I doing wrong?
Well, if this control is in another class library, or even if it's in the same one, it wouldn't be a bad idea to specify control's assembly in #Register:
<%# Register TagPrefix="myControls" Namespace="MyApp.Controls" Assembly="MyApp" %>
<myControls:CustomControl runat="server" Text="What's up!" />
Clean and rebuild your solution too in order to verify everything is compiled rightly!
If your control will be reused on several pages, you may want to register it in web.config, as one of system.web/pages/controls subelements instead of copy-pasting the same <#Register tag in all affected pages.
web.config:
<system.web>
<pages ...>
<controls>
...
<add tagPrefix="myCompany" namespace="MyCompany.Whatever.Controls" assembly="Whatever"/>
</controls>
thepage.aspx:
<myCompany:ControlClassName ID="TheStuff" runat="server" ... />
You should put your control either under the App_Code folder (in the case if the control not in assembly) or add a reference to assembly where this control is:
<%# Register TagPrefix="myControls" Namespace="MyApp.Controls"
Assembly="SomeAssembly" %>
But guessing, your control not under the App_Code folder.
Add an assembly attribute to your register tag
i want disable RequestValidation on particular view in ASP.NET MVC 2.0 RTM. so i added some necessary to view Page directive section as below:
<%# Page ValidateRequest="false" Language="C#" MasterPageFile="Path" Inherits="System.Web.Mvc.ViewPage<Path>" %>
but RequestValidation isn't Disabled! i also added RequestValidation Attribute to related action in controller as below:
[System.Web.Mvc.ValidateInput(false)]
public System.Web.Mvc.ActionResult Create(Model instance)
{
//Do here something
}
:') but RequestValidation isn't Disabled too!
in last try i set RequestValidation to false in Web.config file as below:
<pages validateRequest="false" />
RequestValidation still isn't turned off!
Why? thank's in advance ;)
If you are using asp.net 4.0 the validate request feature behavior has been changed from version 2.0. Check out the breaking changes document here. If this is the case you can resolve the problems by setting the request validation behavior back to the 2.0 in the web.config like this:
<httpRuntime requestValidationMode="2.0" />
just add
[ValidateInput(false)]
in your controller function
but don't forget to encode the value to prevent harmful code
[ValidateInput(false)]
public string Browse(string test)
{
string message = HttpUtility.HtmlEncode("Value = " + test);
return message;
}
I'm trying to develop my first site in ASP.Net using Web Forms.
I have a form with some controls and a TextBox control. While now I use GETrequest. When user submits a form his browser expects to get long URL, something like
http://mysite.com/search.aspx?__VIEWSTATE=%2FwEPDwUJNTE2NjY5jMY4D2QWAgICD2QWAgIDDW8wAh4EVGV4dAUBMWRkZKthQ0zeIP5by49qIHwSuW6nOj8iLTdoCUzpH369xyg8&__EVENTVALIDATION=%2FwEWAwLnrcHhBQLs0bLrBgKM54rGBjGtX5fJOylLy4qRbt6DqPxO%2FnfcMOkHJBRFqZTZdsBD&TextBox1=sfs&Button1=Button
if his input is a word sfs in TextBox1.
So I need to return him response. I would like to show this response on a user-friendly URL like
http://mysite.com/search.aspx?TextBox1=sfs
or
http://mysite.com/sfs
or
http://mysite.com/search/sfs
How can I do that? If I use Response.Redirect, it first returns 302, and only then work on short URL. Server.Transfer doesn't change URL and user sees ugly long URL in browser.
It seems to me that it is possible to solve via RouteCollection.MapPageRoute which appeared in 4.0 Framework but it's unclear to me how I can use it.
Any help is appreciated.
UPDATE. It is not a problem to use POST instead of GET. But in this way URL will always look like http://mysite.com/search.aspx
UPDATE2. The form MUST be server control and it has another controls except submit and textbox. It would be good (though, still, not necessary if this parameters don't appear in URL showing in the browser.
Using GET requests with ASP.NET server forms will unfortunately always yield those "ugly" URLs.
One thing that you can do is change the form to not be a server form and instead be a regular form:
<form method="get" action="Search.aspx">
<input type="text" name="query" />
<input type="submit" name="SearchButton" value="Search" />
</form>
One limitation of this solution is that you can no longer place certain ASP.NET controls within this form. For example, the <asp:Button> control will not work in this form because it must be contained within a server form (that is, a form that has runat="server" on it).
Since its a GET request you can also use javascript, setting the
location.href = 'http://mysite.com/search/' + query;
Then on the ASP.NET side you can use the URL Rewriting feature to redirect that url to a specific ASPX page as a query string parameter.
Let me know if you would like a more detailed sample.
Sample:
Here is a sample, please note I haven't tested it, but this should get you started.
<html>
<head>
<script type="text/javascript">
function searchRedirect()
{
var query = $get('query');
location.href = "/search/" + query.value;
}
</script>
</head>
<body>
<div class="search">
<input type="text" id="query" /><br />
<input type="button" id="search" value="Search" onclick="searchRedirect();" />
</div>
</body>
</html>
Then on the redirect side you have have a RouteModule like this:
public class UrlRewriter : IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.AuthorizeRequest += new EventHandler(OnBeginRequest); //this ensures the login page has the vitual url not the mapped url
}
private void OnBeginRequest(object sender, EventArgs e)
{
var application = sender as HttpApplication;
if (application != null)
{
var requestPath = application.Request.AppRelativeCurrentExecutionFilePath;
if (requestPath.ToLower().StartsWith("/search/"))
{
var query = requestPath.Substring(8);
application.Context.RewritePath("Search.aspx", null, "query=" + query, false);
}
// .. Other Routes
}
}
}
And assuming the code is in your App_Code folder you could use this in your web.config
<system.web>
<!-- ... -->
<httpModules>
<add name="UrlRewriter" type="UrlRewriter, __code"/>
</httpModules>
</system.web>
<!-- If IIS7 -->
<system.webServer>
<modules>
<add name="UrlRewriter" type="UrlRewriter, __code" />
</modules>
</system.webServer>
Well, the main thing that's making that 'look bad', is you're using ViewSate and GET; so don't do that (either disable the ViewSate and adjust code accordingly, or use POST).
What you may also be interested in, however, is URL Re-Writing. You can do that in a few ways, I typically do it with a wildcard mapping in IIS and appropriate changes to the Global.asax file. Searching will reveal how to do this.