Here is a workaround for too long ReturnUrl querystring parameter. The fact is if there was something in the querystring before appending new RedirectUrl parameter (e.g. by using FormsAuthentication.RedirectToLoginPage method), this would be encoded and assigned to the new RedirectUrl parameter.
The idea is to remove unnecessary(old ReturnUrl parameters from the querystring). For this I use Application_EndRequest in global.asax and Response.RedirectLocation property.
So if the response is being redirected and current url contains ReturnUrl parameter, it should be removed from redirected location (because it doesn't make sense).
// parameter key
private static readonly string ReturnUrlParameter = "ReturnUrl";
protected void Application_EndRequest(object sender, EventArgs e)
{
if (Response.IsRequestBeingRedirected)
{
Uri redirectUrl;
if (Uri.TryCreate(Response.RedirectLocation, UriKind.RelativeOrAbsolute, out redirectUrl))
{
redirectUrl = MakeAbsoluteUriIfNecessary(redirectUrl);
Uri currentUrl = Request.Url;
var currentQueryParameters =
HttpUtility.ParseQueryString(HttpUtility.UrlDecode(currentUrl.Query));
// the parameter is present in the current url already
if (currentQueryParameters[ReturnUrlParameter] != null)
{
UriBuilder builder = new UriBuilder(redirectUrl);
builder.Query =
HttpUtility.UrlDecode(builder.Query)
.Replace(Request.Url.Query, string.Empty).TrimStart('?');
Response.RedirectLocation =
Request.Url.MakeRelativeUri(builder.Uri).ToString();
}
}
}
}
private Uri MakeAbsoluteUriIfNecessary(Uri url)
{
if (url.IsAbsoluteUri)
{
return url;
}
else
{
Uri currentUrl = Request.Url;
UriBuilder builder = new UriBuilder(
currentUrl.Scheme,
currentUrl.Host,
currentUrl.Port
);
return new Uri(builder.Uri, url);
}
}
For URL parsing and building System.Uri will be the best choice.
A URI is a compact representation of a
resource available to your application
on the intranet or Internet. The Uri
class defines the properties and
methods for handling URIs, including
parsing, comparing, and combining. The
Uri class properties are read-only; to
create a modifiable object, use the
UriBuilder class.