How do I obtain the current physical url when url routing? - asp.net

I'm using ASP.NET WebPages (not MVC) to route urls in Application_Start in my Global.asax file.
System.Web.Routing.RouteTable
.Routes
.MapWebPageRoute("", "~/Pages/Home.cshtml")
.MapWebPageRoute("products", "~/Pages/Products.cshtml");
How do I obtain the physical url (second parameter given to MapWebPageRoute method) when a request is made?
protected void Application_BeginRequest(object sender, EventArgs e)
{
// I want to be able to retrieve the .cshtml page url in this context
}
I tried Request.Url.AbsoluteUri.ToString() but that only gives me the mapped url.

Related

URL Rewriting exceptional case for removing .aspx extension

My scenario is: I have a website which is ASP.NET WebForm. Users can create their own page on my web site, their page url would be something like this: (MyWebsite.com/UserPage). but It is actually: (MyWebsite.com/UserPages.aspx?q=UserPage). It means when you enter the url (MyWebsite.com/UserPage) It rewrites the url and shows you (MyWebsite.com/UserPages.aspx?q=UserPage) (but the address bar is always like (MyWebsite.com/UserPage).
Here's my code in my "UrlRewriting" class:
void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
if (app.Request.Path.Contains("/") && !app.Request.Path.Contains(".") && app.Request.Path.IndexOf("/") == app.Request.Path.LastIndexOf("/"))
{
string userPageTitle = app.Request.Path.Substring(app.Request.Path.IndexOf("/") + 1);
if (!string.IsNullOrEmpty(userPageTitle ))
{
app.Context.RewritePath(string.Format("UserPages.aspx?q={0}", userPageTitle));
}
}
}
Now here's my problem: as I said my project is ASP.NET WebForm, (So, all of pages have .aspx extension) I wanted to remove the .aspx extension in my Urls, I've tried some codes in web.config which were working properly (In normal cases), but In my case, if you enter (MyWebsite.com/UserPage) It will be considering this "UserPage", as "UserPage.aspx". How can I handle this?
I usually do this with Routing which is available in ASP.NET Web Forms 4+.
You register your routes (URL patterns) in Global.asax, and specify which ASPX page will handle that URL.
This example would have UserPage.aspx handle all URLs that weren't otherwise handled by other ASPX pages.
void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.MapPageRoute("UserPageRoute", "{*url}", "~/UserPage.aspx");
}
Then in your UserPage.aspx you can determine the URL requested by looking at the Request.Url object, eg. Request.Url.PathAndQuery.
Note that you may need some extra web.config settings for this to work, eg (to manage extensionless URL requests)...
<configuration>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />

How to url redirect/rewrite .asp into .aspx

I'm running in the Cassini developer server inside Visual Studio 2012, and I need to redirect clients from the legacy .asp pages to .aspx pages.
Note: Ideally I would redirect clients from .asp to a friendly url, and then internally do a rewrite to .aspx
POST /ResetClock.asp
HTTP/1.1 307 Temporary Redirect
Location: //stackoverflow.us/ResetClock
And then internally:
POST /ResetClock
rewrites into /ResetClock.ashx (Yes, I changed it to .ashx; that's the virtue of url rewriting).
Like what Hanselman did
This is a lot like what Scott Hanselman did:
Request for /foo.html
gives the client a redirect to /foo
client request for /foo
is re-written into /foo.html
The attempted hack
I tried the hack solution; alter the .asp page to force a redirect to the .ashx (and live to fight with the url re-write syntax another day):
ResetClock.asp
<%
Response.Redirect("ResetClock.aspx")
Response.End
%>
Except that Cassini does not serve .asp pages at all:
This type of page is not served.
Description: The type of page you have requested is not served because it has been explicitly forbidden. The extension '.asp' may be incorrect. Please review the URL below and make sure that it is spelled correctly.
Requested URL: /WebSite/FetchTimes.asp
Which points to a related issue. The solution I end up using cannot require anything that isn't already available on the IIS7.5. And it cannot require anything that needs access to the IIS Admin tools; and must exist entirely within the web-site (e.g. the web.config).
The question
How do I re-write .asp into something more ASP.net-ish?
Edit: Changed GET to a POST to thwart nitpickers who wonder why the 307 Temporary Redirect and not 302 Found or 303 See Other.
The solution is to create an IHttpModule. HttpModules let you intercept every request, and react as you desire.
The first step is to create the plumbing of an IHttpModule:
class UrlRewriting : IHttpModule
{
public void Init(HttpApplication application)
{
application.BeginRequest += new EventHandler(this.Application_BeginRequest);
application.EndRequest += new EventHandler(this.Application_EndRequest);
}
public void Dispose()
{
//Nothing to do here
}
private void Application_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
}
private void Application_EndRequest(object sender, EventArgs e)
{
}
}
And then register our HttpHandler in the web.config file:
web.config:
<configuration>
<system.web>
<httpModules>
<add name="UrlRewriting" type="UrlRewriting"/>
</httpModules>
</system.web>
</configuration>
Now we have a method (Application_BeginRequest) that will run every time a request is made.
Issue client redirect if they ask for ASP page
The first order of business is redirect the client to a "clean" form. For example, a request for /File.asp is redirected to /File:
private void Application_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
//Redirct any requests to /File.asp into a /File
if (context.Request.Url.LocalPath == VirtualPathUtility.ToAbsolute("~/File.asp"))
{
//Be sure to issue a 307 Temporary Redirect in case the client issued a POST (i.e. a non-GET)
//If we issued 302 Found, a buggy client (e.g. Chrome, IE, Firefox) might convert the POST to a GET.
//If we issued 303 See Other, the client is required to convert a POST to a GET.
//If we issued 307 Temporary Redirect, the client is required to keep the POST method
context.Response.StatusCode = (int)HttpStatusCode.TemporaryRedirect;
context.Response.RedirectLocation = VirtualPathUtility.ToAbsolute("~/File");
context.Response.End();
}
}
And then the internal rewrite
Now that the client will be asking for /File, we have to re-write that internally to an .aspx, or in my case, an .ashx file:
private void Application_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext context = application.Context;
//Redirct any requests to /ResetClock.asp into a /File
if (context.Request.Url.LocalPath == VirtualPathUtility.ToAbsolute("~/ResetClock.asp"))
{
//Be sure to issue a 307 Temporary Redirect in case the client issued a POST (i.e. a non-GET)
//If we issued 302 Found, the buggy client might convert the POST to a GET.
//If we issued 303 See Other, the client is required to convert a POST to a GET.
//If we issued 307 Temporary Redirect, the client is required to keep the POST method
context.Response.StatusCode = (int)HttpStatusCode.TemporaryRedirect;
context.Response.RedirectLocation = VirtualPathUtility.ToAbsolute("~/ResetClock");
context.Response.End();
}
//Rewrite clean url into actual handler
if (context.Request.Url.LocalPath == VirtualPathUtility.ToAbsolute("~/ResetClock"))
{
String path = "~/ResetClock.ashx"; //no need to map the path
context.Server.Execute(path, true);
//The other page has been executed
//Do not continue or we will hit the 404 of /ResetClock not being found
context.Response.End();
}
}
IIS contains some basic url redirection
Starting with some unknown version of IIS, they added a (now mocked) form of URL Rewriting. It doesn't issuing a client redirect, only an internal re-write. But at least it could be used to solve my problem (responding to an ASP page with ASP.net content):
web.config
<configuration>
<system.web>
<urlMappings>
<add url="~/ResetClock.asp" mappedUrl="~/ResetClock.ashx"/>
</urlMappings>
</system.web>
</configuration>
The client will still appear to have found a resource at /ResetClock.asp, but the guts of the response will have come from /ResetClock.ashx.
Note: Any code is released into the public domain. No attribution required.

Session is null in the new page when transfer the request in the HttpModule

All, I'm trying to implement an HttpModule (IHttpModule) to catch pages request and redirect to a new page. Unfortunately, it seems I can't use the Session in the new page. because the Session is null.
Here is my code looks like. please review it .
public class MyModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
void context_BeginRequest(object sender, EventArgs e)
{
....
HttpContext.Current.Server.Transfer("newpage.aspx");//redirect to new page.
}
}
In the newpage.aspx, There is an exception says Object reference not set to an instance of an object for the code HttpContext.Current.Session[xxx], Because the HttpContext.Current.Session is null .
Could someone tell me what happen to it ?
Thanks.
Update
All, I found If I use the HttpContext.Current.Response.Redirect to redirect url . Everything is ok. I mean the Session object is initiated before being used.But that doesn't work for Server.Transfer.
I already knew what is the difference of these two.
The normal aspx runtime pipeline with 2 modules is:
--> HttpModule_1.BeginRequest(); --> HttpModule_2.BeginRequest(); --> HttpHandler(Page)
<-- HttpModule_1.EndRequest(); <-- HttpModule_2.EndRequest(); <-- HttpHandler(Page)
Imagine HttpModule_1 as your custom module and HttpModule_2 as the aspx session module.
Your custom module is running first, so no session is filled in when your module is running.
When HttpModule_1 is running BeginRequest you add a Server.Trasfer(). Now, the server transfer will execute the HttpHandler of the request page immediately, it will be called without leaving the BeginRequest and after the handler is done the transfer method will run the Request.End() and terminate the processing.
So, the handler for the "newpage.aspx" will also run before the session module. (actually, the session module will never run because Server.Transfer() will end the request).
If you guaranty that the session module is processes before your module you should resolve the problem (see https://stackoverflow.com/a/2427632/953144).

Redirect Web Page Requests to a Default Sub Folder

I am using UltiDev Web Server Pro and have all my aspx files are located in a sub folder 'WebForms'.
I want to be able to default all requests for pages to this folder such that they can just type:
http://myserver/somepage.aspx instead of
http://myserver/WebForms/somepage.aspx.
Is this possible?
EDIT:
Here is the VB.NET version of the solution below including a check for case sensitivity:
If Not HttpContext.Current.Request.Path.ToUpper.Contains("/WEBFORMS/") Then
Context.RewritePath("/WebForms" + HttpContext.Current.Request.Path, False)
End If
You can use the Global.asax and the Application_BeginRequest to RewritePath to the final destination and still have the link without the WebForm path.
protected void Application_BeginRequest(Object sender, EventArgs e)
{
if(!HttpContext.Current.Request.Path.Contain("/WebForms/"))
RewritePath("/WebForms" + HttpContext.Current.Request.Path, false);
}

Membership API ASP.NET

It is necessary to register as soon as this user directly login
protected void Button1_Click(object sender, EventArgs e)
{
Membership.CreateUser(FNBox.Text, PassBox.Text, EmailBox.Text);
FormsAuthentication.RedirectToLoginPage(FNBox.Text);
}
Error:
"Could not find the resource.
Description: HTTP 404. Perhaps the desired resource (or one of its dependencies of components) is removed, has a different name or is temporarily unavailable. Look at the following URL-address and make sure it is correct.
The requested URL: / OrderTest2/login.aspx "
protected void LoginButton_Click(object sender, EventArgs e)
{
Control lgnview = (Control)LoginView2.FindControl("LoginForm");
TextBox usrbox = (TextBox)lgnview.FindControl("UserName");
TextBox pasbox = (TextBox)lgnview.FindControl("Password");
string user = usrbox.Text;
string pass = pasbox.Text;
if(Membership.ValidateUser(user,pass))
{
FormsAuthentication.RedirectToLoginPage(user);
}
}
This is work normally
Your default redirect login page is wrong. As you can see, you are getting a 404 error which means that IIS cannot find your OrderTest2/login.aspx page. Verify your path.
You can set the defaultUrl path in your web.config as below to a valid page path, this will fix the problem.
<authentication mode="Forms">
<forms loginUrl="/OrderTest2/login.aspx" defaultUrl="myCustomLogin.aspx" cookieless="UseCookies" />
</authentication>

Resources