My asp.net page dynamically displays 207 questions (I can't control this). Each question have 10 validators. When ASP renders the page it creates following three lines for each validator:
var qsnQuestionSet_adult_qcQuestion_1_vldMaxAnswersValidator = document.all ? document.all["qsnQuestionSet_adult_qcQuestion_1_vldMaxAnswersValidator"] : document.getElementById("qsnQuestionSet_adult_qcQuestion_1_vldMaxAnswersValidator");
qsnQuestionSet_adult_qcQuestion_1_vldMaxAnswersValidator.display = "Dynamic";
qsnQuestionSet_adult_qcQuestion_1_vldMaxAnswersValidator.evaluationfunction = "CustomValidatorEvaluateIsValid";
Althrough these three lines are just 4kb you can imagine that 4*10*207 is quite a lot. How can I mark all validators as dynamic and set evaluationfunction to same value without asp generating the line for me?
This code is generated automatically by ASP.NET when the EnableClientScript option is set to true. As far as I'm aware the only way to get rid of it would be to set this to false however the obvious drawback is the validation will only happen on the server side during a postback.
To get around this you could tie the custom javascript validation function to the related control event such as a textbox onBlur event but without knowing more detail about what values you are trying to validate it is difficult to speculate further as to whether this could be a solution.
This javascript is rendered to the client by the AddAttributesToRender() method of the BaseValidator & CustomValidator classes from the System.Web.UI.WebControls namespace. Take a look at them in Reflector.
Protected Overrides Sub AddAttributesToRender(ByVal writer As HtmlTextWriter)
...
If (enumValue <> ValidatorDisplay.Static) Then
Me.AddExpandoAttribute(writer2, clientID, "display", PropertyConverter.EnumToString(GetType(ValidatorDisplay), enumValue), False)
End If
...
MyBase.AddExpandoAttribute(writer2, clientID, "evaluationfunction", "CustomValidatorEvaluateIsValid", False)
End Sub
You could write your own class to replace CustomValidator and change the way that it renders.
But, in this case I think it would be better to write your own javascript to handle validation and not use the validator controls.
P.S. If you're worried about the size of the HTML the first thing you should do is enable gzip compression on your IIS server.
Related
I've recently added an UpdatePanel to a single webpage which renders different usercontrols on button clicks. I'm struggling with a problem where i'm adding inline styling into the header dynamically with Header.Stylesheet.CreateStyleRule - the problem is that it doesn't get inserted on partial postbacks and it does make sense. This is obviously because it's a partial postback and the header is only being rendered when the page loads the first time.
The styling is being added by the following methods, which gets the styling from a database:
Private Sub InitializeStylesheet(ByVal ButtonId As Integer)
Dim CSSStylesheet As Stylesheet = StyleBackend.GetStylesheets(ButtonId)
Dim IdClassList As List(Of StyleIDClass) = StyleBackend.GetStylesheetsStyleIDClass(CSSStylesheet.StylesheetID)
'Iterates through the cssidclass
For Each cssidClass In IdClassList
Dim styleItems As List(Of StyleItem) = StyleBackend.GetStyleItemsByIDorClass(cssidClass.StyleIDClassID)
Dim cssString As String = Nothing
For Each StyleItem As StyleItem In styleItems
cssString += StyleItem.Property & ":" & StyleItem.Value & ";"
Next
'Iterates all cssitems which belongs to a cssidclass
Me.Header.StyleSheet.CreateStyleRule(New CustomStyle(cssString), Nothing, cssidClass.ClassOrID)
Me.Header.ViewStateMode = UI.ViewStateMode.Disabled
Next
End Sub
I've been googling my ass off trying to get this to work, but it seems to be impossible.
This msdn article literal says that it is impossible to do what i'm trying to do.
http://msdn.microsoft.com/en-us/library/system.web.ui.htmlcontrols.htmlhead.stylesheet.aspx
Adding styles or style rules programmatically during asynchronous postbacks is not supported. When you add AJAX capabilities to an ASP.NET Web page, asynchronous postbacks update regions of the page without updating the whole page. For more information, see Microsoft Ajax Overview.
Does anyone have a suggestion or alternative way of doing this?
Thank you!
One solution is just to include the styles in your main stylesheet(s) rather than modifying them dynamically. Even if they are data-driven, you could output them with the main page via an HTTP handler if the total list isn't too large.
Alternatively (and probably more efficiently), you can return the style data to the client as a string and process it there.
You can listen for the EndRequest event on the client script manager:
function endRequest(){
// look at the updated DOM
}
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequest);
Perhaps the following sequence:
Initiate async postback
Render the styles to a hidden field inside the UpdatePanel
On endRequest, examine the DOM to see if it contains a hidden field with styles (based on naming convention, data attributes, or just ID)
Grab the values out of the hidden field and add them to the page's style rules using JavaScript
I am creating a web user control for a simple poll. I am currently registering it on the page and then referencing it via tagprefix.
The form for the poll is in basic html (no server controls) and is in the front-end of the web control. How can I change the look of the user control depending on the settings passed into it? Is this possible without using server controls?
Update
Can I change the html layout of a user control? If so could someone post some examples. Please note I do not use asp.net form controls, so none of that please :)
You might be able to also use jQuery to replace existing css setting in your code. Create properties on for your user control, and then pass settings in the classes. Then use jQuery to replace them. This however requires jQuery to be linked to your page (or within your control) and you'd have to write the CSS classes out to the jQuery code (using server controls, but you could use the literal control so there's no excess code).
Personally I'd go with the option of using server controls instead of straight up HTML, you'd get alot more flexibility, and then passing through the settings would be pretty straightforward, put something like this in your controls backend code:
Private _TextBoxCssClass As String
Public Property TextBoxCssClass() As String
Get
Return _TextBoxCssClass
End Get
Set(ByVal value As String)
_TextBoxCssClass = value
txtBox1.CssClass = value
txtBox2.CssClass = value
End Set
End Property
You most likely want to have a property or event in the control that changes the css. It may end up best to add some server controls or javascript / jquery to make it easier.
If its only the styles you want to change, then you can expose a property to set the style attribuites of the respective control inside your User Control. If you want to control the whole HTML layout of the control then Custom Control is the viable option.
I find it hard when using asp.net controls, to make proper css files because I don't know what the html output for the different controls end up as.
For example, if I want to add a div tag using a asp.net control, it's not easy to know what kind of control I can use.
Are there any documentation that shows for each asp.net control, what the rendered html for that control will be? I understand that some controls will probably change it's output due to how it's configured, but most controls will at least follow a pattern here.
The best would of course be a service on the web where you can put in the asp.net control definition and get the rendered html out.
Currently I have to put a control into my webform, run it and check the source in the browser, and if it's not the correct html tag, try another control and repeat. That get's tedious quite fast.
If you want to know to what html-controls a server-control is rendered, you could call RenderControl:
Dim myGridView as new GridView
Dim sb as New StringBuilder()
Dim sw as New IO.StringWriter(sb)
Dim textWriter as New HtmlTextWriter(sw)
myGridView.RenderControl(textWriter)
' now we can have a look what asp.net has rendered: '
Dim gridViewHTML as String = sb.ToString()
The rendered html will even differ from browser to browser for example when ASP.Net thinks the client uses a "lower"-browser(BrowserCaps), a Panel will be rendered as Table instead of a DIV.
By the way, if you're testing my above code on controls inside of your page, you have to override VerifyRenderingInServerForm otherwise you get a "...must be placed inside a form tag with runat=server"-error:
Public Overrides Sub VerifyRenderingInServerForm(ByVal control As System.Web.UI.Control)
Return
End Sub
I would recommend adding a CssClass to your WebControls, and doing all your styling using classes, rather than HTML element types. As Tim Schmelter says, the html can render differently for different clients (I seem to remember a Panel can be a span as well under certain circumstances).
To avoid actually having to add the CssClass each time, you can subclass the WebControl you want, then set it's CssClass in Control_Init.
I have a CustomValidator, RequiredFieldValidator and ValidationSummary controls on an aspx page to check the current password and make sure the new password is not blank.
When I click submit I get the js alert() box from the summary control telling me about just the RequiredFieldValidator being false, but the client script for the CustomValidator does not seem to get its return value used. I have checked the "arguments.IsValid" value using FireBug, so it is getting called and returning the correct bool, but it never shows up in the val summary box?
Thanks,
Goosey
Its hard to say what is going on without the code. As a side note, you might want to check out the xVal framework as I think it handles what you are looking to do.
Is there a difference in behavior between adding a control to the ASPX page directly and loading a control programmatically and adding to a placeholder?
The control inherits from System.Web.UI.WebControls.DataBoundControl.
The reason I ask is that I have a control that works when I add it to the ASPX page like so:
...
<blah:GoogleMap ID="GoogleMap1" runat="server" Width="640px" Height="600px" ... DataSourceID="_odsMarkers" DataAddressField="Address" DataTextField="Description">
</blah:GoogleMap>
...
But not when I use the following in a codebehind page:
GoogleMap map = (GoogleMap)this.LoadControl(typeof(GoogleMap), new object[] { });
//... set properties
this.placeholder1.Controls.Add(map); //add to placeholder
Anyone have any ideas why this might be the case?
The control tree ends up the same if you define in markup or add programmatically. However there is plenty of room for the control implementor to screw up along the way.
You can go look how ASP.NET compiles the aspx:
C:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files
The timing when the control is added to the page might be an issue. The usual pattern is add the control in an overload of the CreateChildControls method. If the control needs to resolve viewstate you need to make sure this is called during init, e.g. by calling EnsureChildControls.
Adding to ninja's debbugging hint. Does it make any difference if you add a label the same way. Does it show up?
Is this a user control or server control?
If it's a user control they should be loaded by their path and not their type:
GoogleMap map = (GoogleMap)this.LoadControl("~/Controls/GoogleMap.ascx");
If it's server control then you can just new up an instance:
GoogleMap map = new GoogleMap();
after you have the instance and add it to the control tree (by inserting it into the PlaceHolder) it should perform the same as when it would have been declared in the markup.
If you are setting properties outside of the LoadControl call, why are you making that new empty object array instead of just using the overload that has one parameter?
Also, if you attach a debugger to it and step through, do you notice anything weird about the control before you do your Controls.Add() call? Is there an exception being thrown? if so, which one? if not, what does the markup in the browser look like for where the placeholder is?
"Works" is kind of ambiguous, but if you mean, event handlers are never executed, you need to load it in the page onload event.
If the control requires the use of viewstate you must ensure that it is added to the page BEFORE the Page_Load event, otherwise viewstate will not be populated and most likely events and other items will not function properly.
One important difference is that if you create a control dynamically, you will not get, by default, any values from skins set. You must manually call control.ApplyStyleSheetSkin(page): http://msdn.microsoft.com/en-us/library/system.web.ui.control.applystylesheetskin.aspx