Search Results for 'postback' ↓

ASP.NET: Access Controls after using PostBackUrl

Whenever you execute a Cross Page Post-Back from one site to another by using

<asp:button PostBackUrl=“anotherpage.aspx" runat=“server"/>

be sure to set this on anotherpage.aspx to gain full access to the controls of the previous page:

<%@ PreviousPage VirtualPath=“previouspage.aspx" %>

Afer that, you can access the controls by using the Page.PreviousPage Property.

Example:

Textbox MyNewTextBox = PreviousPage.FindControl("PreviousPageTextBox");
Label1.Text = MyNewTextBox.Text;

Cheers!

Make the ASP.NET DataPager SEO friendly?

Currently I’m working on a brand new .NET Framework v4 Project which is using all the new stuff of the new framework version. So I decided to try out the ASP.NET DataPager once more. It was introduced in previous .NET Versions already. However, at the beginning it only provided Javascript/Postback URLs which were not crawlable by searchengines. I mentioned that on Scott Gu’s Blog back in the day, maybe that helped the process to include a “QueryString” Option. You can define the DataPager using this options:

 <asp:DataPager runat="server" ID="DataPager1" PageSize="10" PagedControlID="listViewProducts" QueryStringField="pageNumber">

By using the “QueryStringField” option it at least won’t create uncrawlable Javascript/Postback Links. However, URLs like www.domain.com/?pageNumber=2 still won’t satisfy my needs. The best solution would be to integrate the Datapager with URL Routing. What we need for SEO is Static URLs like www.domain.com/page/2/ and nothing less! I saw a post on codeproject which explains how to extend the Datapager using that kind of searchengine friendly URLs, but it got some annoying limitations:

  • It does not support postback for paging.
  • Only the Next/Previous etc., pager style is supported, not a list of page numbers with direct jump capability.
  • There is no declarative way to display paging information (e.g., “showing items 1-10 from 100, page 1 of 10”).

Due to those facts I unfortunately still need to use my own custom solution. I would love to see a Datapager / URL Routing integration in the future!

404 Error while using ASP.NET URL Routing

I’m heavily using the new ASP.NET URL Routing feature introduced in .NET Framework 3.5 SP1 in my new ASP.NET Applications instead of traditional URL Rewriting. I actually wanted to use IIS7 URL Rewriting, but there’s no way to test your rewrite rules if you are using the built-in VS2008 Cassini Webserver for development (yet).

So I’ve set up some sweet URL Routing rules with Webforms and I have to say it works pretty good so far. However, sooner or later I stumbled upon the first problem. I used an UpdatePanel on a webform which went through the URL Routing mechanism. As soon as I hit the postback button I got the following error:

Sys.WebForms.PageRequestManagerServerErrorException: An unknown error occurred while processing the quest on the server. The status code returned from the server was: 404.

Obviously because the form action attribute didn’t supply the full URL and that is the problem. You can fix it by adding this to your Page_Load:

form1.Action = HttpContext.Current.Request.RawUrl;

I just added it into the MasterPage Page_Load as I’m using URL Routing all over the Page. That’ll fix it.

I’ve also seen this:

if (!String.IsNullOrEmpty(Request.ServerVariables["HTTP_X_ORIGINAL_URL"]))
        {         
          form1.Action = Request.ServerVariables["HTTP_X_ORIGINAL_URL"];
        }

However, that snippet doesn’t work for me, I actually don’t know why. If that’s the case for you, too, just use the RawURL snippet above (without an if block).

Follow Up: Enable ValidateRequest in ASP.NET and still read HTML

Last week I read a great post on Mad’s Blog about Re-Enable Request Validation in ASP.NET. He built a javascript function which automatically HTMLEncodes the Text on Clientside when the User hits Submit by using Tagmapping and automatically HTMLDecodes it on server-side.

By using his technique you can still benefit of the ValidateRequest Security while allowing HTML in your forms.

Now to the Follow Up: If you use ASP:Panels on your webform and you hide specific Panels which do include Textboxes to show them just on specific events you run into a Javascript Error saying tb is null. That’s because the HTML Output which is dynamically created doesn’t contain the textbox when the Panel is hidden, although ASP.NET is executing the JS Statement for those hidden textboxes anyway and that’s when the Error pops up. You can fix that pretty easy by checking if tb is null, here’s Mad’s Code containing that little fix:

public class SafeTextBox : System.Web.UI.WebControls.TextBox
{
protected override void OnLoad(System.EventArgs e)
{
base.OnLoad(e);
if (!Page.ClientScript.IsClientScriptBlockRegistered(Page.GetType(), "TextBoxEncode"))
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append("function TextBoxEncode(id)");
sb.Append("{");
sb.Append("var tb = document.getElementById(id);");
sb.Append("if (tb != null){"); //fix
sb.Append("tb.value = tb.value.replace(new RegExp('<', 'g'), '<');");
sb.Append("tb.value = tb.value.replace(new RegExp('>', 'g'), '>');");
sb.Append("}");
sb.Append("}");
Page.ClientScript.RegisterClientScriptBlock(Page.GetType(), "TextBoxEncode", sb.ToString(), true);
}

// Adds the function call after the form validation is called.
if (!Page.IsPostBack)
Page.Form.Attributes["onsubmit"] += "TextBoxEncode('" + ClientID + "');";
}

public override string Text
{
get { return base.Text; }
set
{
if (!string.IsNullOrEmpty(value))
base.Text = value.Replace("<", "<").Replace(">", ">");
else
base.Text = value;
}
}
}

Read Mad’s full article on how to implent this technique and be sure to turn ValidateRequest back on!

ListView and DataPager

Now I’m really missing my CopyToHTML Plugin back from Visual Studio 2005 :o. Here is a little example on how to use the new ListView Control and DataPager of the .NET Framework 3.5:

<asp:ListView ID=”ListView1″ runat=”server” DataSourceID=”SqlDataSource1″ ItemContainerID=”DataSection”>

<layouttemplate>
StartLayout:<br /><br />
<div id=”DataSection” runat=”server”></div>
EndLayout!<br /><br />
</layouttemplate>

<ItemTemplate>
<div class=”usRevs”>
<div class=”criticscore”>
<%# DataBinder.Eval(Container.DataItem, “Rating”)%></div>
<div class=”criticreview”>
<div class=”quote”>
<%# DataBinder.Eval(Container.DataItem, “Title”)%></div>
</div>
</div>
</ItemTemplate>

</asp:ListView>

<asp:DataPager ID=”DataPager1″ runat=”server” PagedControlID=”ListView1″ PageSize=”4″>
<fields><asp:nextpreviouspagerfield ButtonType=”Button” ShowFirstPageButton=”True” ShowNextPageButton=”False” ShowPreviousPageButton=”False” /><asp:numericpagerfield />
<asp:nextpreviouspagerfield ButtonType=”Button” ShowLastPageButton=”True” ShowNextPageButton=”False”
ShowPreviousPageButton=”False” />
</fields>
</asp:DataPager>

<asp:SqlDataSource ID=”SqlDataSource1″ runat=”server” ConnectionString=”<%$ ConnectionStrings:LocalSqlServer %>”
SelectCommand=”SELECT [Title],[Rating],[Description],[Developer] FROM [gf_game]”></asp:SqlDataSource>

That’s it, here is how it looks:
ListView Datapager

However, there is one big downside of the DataPager: If you build a Website which needs to score in SEO matters you wouldn’t want to use the DataPager. As of now the links to the pages look like that:

javascript:__doPostBack(‘ctl00$ContentPlaceHolder1$DataPager1$ctl01$ctl02’,”)

A SearchEngine won’t be able to follow this link, which means you eventually run into problems if you want to get a heavy paged site indexed in a SearchEngine by using the DataPager Module in that kind of way.

Here’s how it would need to look like for e.g. page 2:

yoururl.com/pagedsite.aspx?p=2 or even better: yoururl.com/pagedsite.aspx/2/

The PagerData Control is really amazing but if it’s missing the SEO aspect I can’t use it for my public SEO oriented sites..

UPDATE: Here you can find a querystring based DataPager built by Polita Huff: click. Great!

Disable Button after ASP.NET Async Webservice Call

With ASP.NET Ajax and ASP.NET v2.0 it is a piece of cake to create an asynchronous Webservice these days.

However, what if that needs about 45 minutes or even longer to complete? You know your users, many people will hit the button again after 10 minutes because they think it will be faster that way, or they accidently double click it. Just imagine people standing at a traffic light and hitting the “Get Green Button” like a thousand times. The result of this is an unwanted increase of the server load by starting an additional webservice process with every click.

Here is a very easy solution to pretend this, add this to the Button which fires the async webservice call, in my case Button1:

   41 Button1.Attributes.Add(“onclick”, ” this.disabled = true; “ + ClientScript.GetPostBackEventReference(Button1, null) + “;”);

That’s it! The button will be disabled until the final PostBack is taking place. Of course your controls need to be in an UpdatePanel for this to work.

Validation of ViewState Mac failed

Probably many of you know this exception:

[HttpException (0x80004005): Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster.]

If your page doesn’t load slowly and you are not on a web farm, this little tipp might help you. Most people suggest to add the following attributes to the Page directive:

<pages enableEventValidation=false viewStateEncryptionMode =Never

This is known to be a security risk and in my case it didn’t fix the problem.

I think I found another way to eliminate the Error, add this to your Button which triggers the Postback Event:

   23 PostBackUrl=”~/yoursite.aspx”

Just post it back to the same site explicitly and you should be fine.

Edit: Another discovery, you can use the maxPageSateFieldLength attribute of the Pages element in the web.config. That will split the viewstate across multiple hidden fields if the content length is larger than maxPageSateFieldLength.

Hope that helps!