I am trying to get this to work. I have a DNN module in which I read from a querystring and perform a few steps. All of that is working fine. Now I am trying to clean up the URL while reading the querystring
Right now, the URL looks something like this:
http://mysite.website.com/?pid=1234
I would like it to look like:
http://mysite.website.com/1234
Is something like this even possible?
You are much better to use a proper rewriting solution for DotNetNuke (e.g. iFinity UrlMaster and there are others...).
You can then write a custom url provider for your module.
That's what I've done on my site to rewrite parts of my articles module (e.g. www.ventrian.com/blog/
You can find more information about urlmaster here:
http://www.ifinity.com.au/Products/Url_Master_DNN_SEO_Urls
look at using a URL Rewriter module. There are several third party ones for IIS6, but Microsoft provides one for IIS7 and IIS7.5. You basically configure it with a regular expression and change the output.
Microsoft's rewrite module for IIS7 is available at: http://www.iis.net/downloads/microsoft/url-rewrite
You've got a couple of choices:
Explore the rewrite capabilities available in DNN and how to use them. They can be found in Host Settings > Advanced Settings > Friendly URL Settings. Or use the 2nd option based on which version of IIS you're working on.
2a. URL Rewrite Module for IIS 7 & above
2b. "ISAPI_Rewrite 3" by HeliconTech (has free version too, that does the job pretty well)
You can accomplish what you are looking for without interacting with DNN at all by using an HttpModule. Kind of like this:
public class PidRewriteModule : System.Web.IHttpModule
{
public void Dispose()
{
}
public void Init(System.Web.HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication app = sender as HttpApplication;
if (app != null)
{
Match mPidCheck = new Regex(#"^/(?<pid>[0-9]+)/?$").Match(app.Context.Request.Url.AbsolutePath);
if (mPidCheck.Success)
{
app.Context.RewritePath("~/default.aspx", String.Empty, String.Concat("pid=", mPidCheck.Groups["pid"].Value));
}
}
else
return;
}
}
Then you can add this to your Web.config:
<modules runAllManagedModulesForAllRequests="true">
<add name="PidRewriteModule" type="Assembly.Namespace.PidRewriteModule, Assembly"/>
</modules>
Put that in the system.webServer node. Substitute Assembly and Namespace respectively.
All of this info is for IIS7. It's not entirely different for IIS 6, but previous implementations you have to go the route of ISAPI filters.
Related
I'm trying to implement a custom http security module that uses the roles in the sitemap to control access to pages (instead of having to store it all in the web.config as well). Following article here: http://www.codeproject.com/Articles/8728/Extending-ASP-NET-security
I've updated it for the newer versions of IIS, adding the module in system.webServer instead
<system.webServer>
<modules>
<add name="SecurityHttpModule" type="DINO.SecurityHttpModule"/>
</modules>
</system.webServer>
Everything seems to be working alright in respect to that, but pages are no longer rendering correctly. If I look at the console in Chrome I am seeing errors like
Resource interpreted as Stylesheet (or Script) but transferred with MIME type test/html: "http://localhost:57855/login"
and
Uncaught SyntaxError: Unexpected token < (about the <!DOCTYPE html> at the top of the page)
I assume I'm just missing something else I need to do when I'm adding a custom module, but I have not yet been able to find any reference to this issue.
Oguz Ozgul was correct in his comment. To fix it, I added a list of extensions I want to validate permissions for and then I check that as the first part of my authenticate request method.
private static readonly List<string> extensionsToValidate = new List<string>(new string[] { ".aspx", "" });
private void AuthenticateRequest(Object sender, EventArgs e)
{
//Ignore specified extensions from redirection
string CurrentExt = Path.GetExtension(HttpContext.Current.Request.Url.LocalPath);
if (extensionsToValidate.Contains(CurrentExt))
{
//do all security check work here
}
else return;
}
I need to rewrite the URL using ASP.NET with code behind as C#. My Application contains the following URL...
http://www.mywebsite.com/Products.aspx?id=1&pg=1
However, I need to rewrite the URL in such a way that the user gets the same contents of the above URL when the user types the following URL...
http://www.mywebsite.com/CategoryName/ProductName/1
Can any of you guys help me with the complete necessary code how to do it?
I mean the web.config, Global.asax, etc...
If you have IIS7, the best option would be to use IIS Url Rewrite Module.
There might be a couple of options I could suggest:
One
You could look at setting up an HttpHandlerFactory.
I have written one myself: http://mvcsnippets.blogspot.co.uk/2012/10/custom-cms-using-httphandlerfactory.html
here is the basic gist:
namespace Web.Helpers {
public class HttpCMSHandlerFactory : IHttpHandlerFactory
{
public IHttpHandler GetHandler(HttpContext context, string requestType, string url,string pathTranslated)
{
string pageName = Path.GetFileNameWithoutExtension(context.Request.PhysicalPath);
//on Server.Transfer the context is kept, so this just overrides the existing value.
if (context.Items.Contains("PageName"))
{
context.Items["PageName"] = pageName; } else { context.Items.Add("PageName", pageName); }
FileInfo fi = new FileInfo(context.Request.MapPath(context.Request.CurrentExecutionFilePath));
//if File is not physical
if (fi.Exists == false)
{
//return page to CMS handler the context containing "PageName" is passed on to this page, which then calls to the database to return the copy.
return PageParser.GetCompiledPageInstance(url, context.Server.MapPath("~/CMSPage.aspx"), context);
}
else
{
// Returns real page.
return PageParser.GetCompiledPageInstance(context.Request.CurrentExecutionFilePath, fi.FullName, context);
}
}
}
The behaviour I was trying to handle was that if there might be CMS content and I didnt want to have to create a page each time I needed information served, but if a physical page exists that should be returned.
For you, you might want to accept the URL, break it down to the component parts.
so http://www.mywebsite.com/CategoryName/ProductName/1 becomes:
context.Items["Categoryname"] = valueFromUrlasCategoryName;
context.Items["Productname"] = valueFromUrlasProductName;
context.Items["Id"] = valueFromUrlasId (or pg);
return PageParser.GetCompiledPageInstance(url, context.Server.MapPath("~/ControlPage.aspx"), context);
Then on your control page you can intercept these values from the context passed in and interrogate the data as needed.
In the web.config you point a reference towards your HttpHandlerFactory
<httphandlers>
<add path="*.aspx" type="Web.Helpers.HttpCMSHandlerFactory, Web.helpers" verb="*"/>
</httphandlers>
In your case you could set the path as "." to capture all traffic. this would mean you would have to add handling for images and scripts.
you will also need to make sure you add a wildcard to your IIS for extensionless pages.
There are plenty of articles about HttpHandlerFactories on the web, and might explain better.
Two
The sort of thing you are after is part of MVC, could you look at changing your UI to use that?
How can i change view like "www.abc.com/welcome" in browser but actual path is "www.abc.com/welcome.aspx".
And when i type "www.abc.com/welcome" then will go path "www.abc.com/welcome.aspx" but still view like "www.abc.com/welcome".
I have try this code on web.config below but got error:Unrecognized configuration section urlMappings
<urlMappings enabled="true">
<add url="~/welcome.aspx" mappedUrl="~/welcome" />
</urlMappings>
I wonder still got other way?
Where did you get the information about this urlMappings section? It's not supported by default by IIS or ASP.Net.
I think you might want to look at the UrlRewrite Module.
With this it's trivial to setup url rewrites like the one you want.
If you're using a URL rewriting module, you need to make sure which version of IIS you will be running on before something like "/welcome" will work. IIS6 doesn't support extensionless URLs by default. You'll need to have an ISAPI filter running for it, or you'll need to run on IIS7.
I suggest you to use routing How to: Use Routing with Web Forms.
You will need to register the UrlRoutingModule and the UrlRoutingHandler handler to be able to use routing feature (more details could be found in the article above).
And then in global.asax
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.Add("BikeSaleRoute", new Route
(
"bikes/sale",
new CustomRouteHandler("~/Contoso/Products/Details.aspx")
));
}
I have an ASP.NET / C# website that's hosted on Windows Azure. The site is a predictions-based social site with a feed of prediction summaries on the main page. If you click on a summary, you're redirected to the details page for that prediction using a simple QueryString.
For example:
http://www.ipredikt.com/details.aspx?id=14
This particular prediction is entitled "Paris Hilton will win the Nobel Peace Prize" so what I'd like to do is implement URL rewriting for my site on Azure as follows:
http://www.ipredikt.com/predictions/14/paris-hilton-will-win-the-nobel-peace-prize
What are some strategies and best practices for doing this? And can someone point me to a good Azure-specific article or two.
The hyphenated title ("paris-hilton-bla-bla") is really just to make the URL more human readable; I don't envision relying on it at all in terms of loading pages. In fact, I'd probably allow duplicate titles since I'll be relying on the prediction ID in the URL.
EDIT:
Forgot to mention that we are NOT based on MVC. We came up w/ our own architecture that uses PageMethods and WebMethods to return JSON to the client. We rely on ASP.NET AJAX to do all of the JSON serialization, and almost all of our UI is built dynamically on the client using jQuery.
EDIT: SOLUTION
Thought I'd share my solution now that I have things up and running.
I made a new class as follows (copied verbatim from somewhere):
public class WebFormRouteHandler<T> : IRouteHandler where T : IHttpHandler, new()
{
public string VirtualPath { get; set; }
public WebFormRouteHandler(string virtualPath)
{
this.VirtualPath = virtualPath;
}
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return (VirtualPath != null)
? (IHttpHandler)BuildManager.CreateInstanceFromVirtualPath(VirtualPath, typeof(T))
: new T();
}
}
I added the following method to Global.asax. The actual method is MUCH, much longer (it covers every page in the site). You'll see that I support calling the predictions page in lots of different ways: with an id, with an id + title, etc. (The "...fb" versions of pages are for the Facebook app version of my site which use a different MasterPage.)
public static void RegisterRoutes(RouteCollection routes)
{
// Details : 'predictions' Page
var routeHandlerDetails = new WebFormRouteHandler<Page>("~/details.aspx");
var routeHandlerDetailsFb = new WebFormRouteHandler<Page>("~/detailsfb.aspx");
routes.Add(new Route("predictions/{id}", routeHandlerDetails));
routes.Add(new Route("predictions/{id}/{title}", routeHandlerDetails));
routes.Add(new Route("fb/predictions/{id}", routeHandlerDetailsFb));
routes.Add(new Route("fb/predictions/{id}/{title}", routeHandlerDetailsFb));
}
...and this method is called from Application_Start()
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
}
Then I added the following to web.config in the system.webServer block:
<!-- Added for URL Routing -->
<modules runAllManagedModulesForAllRequests="true">
<add name="UrlRoutingModule"
type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</modules>
<!-- Added for URL Routing -->
<handlers>
<add name="UrlRoutingHandler"
preCondition="integratedMode"
verb="*"
path="UrlRouting.axd"
type="System.Web.HttpForbiddenHandler, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</handlers>
I also had to exclude the virtual "predictions" directory from authentication (because almost all parts of our site are accessible my non-auth users):
<!-- Url routing -->
<location path="predictions">
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
</location>
Finally, I no longer rely on QueryString string parameters when loading pages, so I had to write some new helper methods. Here's one that extracts a numerical value from the new routing URL (I'll be cleaning this up to only have a single 'return'.):
public static int GetRouteDataValueAsNumber(HttpRequest request, string propertyName)
{
if ((request == null) ||
(request.RequestContext == null) ||
(request.RequestContext.RouteData == null) ||
(request.RequestContext.RouteData.Values[propertyName] == null))
{
return -1;
}
try
{
return System.Convert.ToInt32(request.RequestContext.RouteData.Values[propertyName]);
}
catch
{
}
return -1;
}
Now when I need to read a routing value (like a prediction ID), I do the following:
long _predictionId = System.Convert.ToInt64(WebAppUtils.GetRouteDataValueAsNumber(Request, "id"));
Works great! Now my site feels like an MVC app with friendly and self-documenting URLs.
Oh, last thing, you also need to enable HTTP Redirection as follows:
Start => Control Panel => Program => Turns Windows Features On => Internet Information Services => World Wide Web Services => Common HTTP Features => (select checkbox for) HTTP Redirection.
The easiest way to implement this would be a programmatic approach using the System.Web.Routing assembly.
This basically works by including the UrlRoutingModule in your web.config, and defining patterns that resolve the target page based on matching routes. If you are familiar with ASP.NET MVC, then you have used this routing strategy before, but MVC is not necessary to use Routing.
Here are some resources to help you get started:
MSDN Documentation for the System.Web.Routing namespace - official documentation
Scott Gu on URL Routing for MVC - * Note that this article explains routing in the context of an ASP.NET MVC application, however, the same methodology will work regardless of whether or not you are using MVC
ASP.NET Routing... Goodbye URL rewriting, by Chris Cavanagh - An explanatory article
Exploring System.Web.Routing, by Justin Etheredge - A case study explaining how to use routing independently of the MVC architecture
About Windows Azure ...
If you take this approach, it doesn't really matter that you are using Windows Azure. However, I found an article by Michael Kennedy called ASP.NET Routing in Windows Azure Using WebForms, explaining how to easily deploy such a solution on Windows Azure. The article even has a sample project for download.
Azure web roles have the IIS7 Url Rewriting module installed - http://msdn.microsoft.com/en-us/library/dd573358.aspx
The "how to" for this module is at http://learn.iis.net/page.aspx/460/using-the-url-rewrite-module/
For your Paris example, you basically need to setup a rule that maps the url
http://www.ipredikt.com/predictions/14/paris-hilton-will-win-the-nobel-peace-prize
to
http://www.ipredikt.com/details.aspx?id=14
This is something like:
Pattern -
^predictions/([0-9]+)/([_0-9a-z-]+)
Action -
details.aspx?id={R:1}
For more on defining these rules see http://learn.iis.net/page.aspx/461/creating-rewrite-rules-for-the-url-rewrite-module/
Objective was:
To change pages like details.aspx?GUID=903901823908129038 to clean ones like /adrian_seo
Achieved:
Now using Response.AddHeader("Location", url);
I am able to remove all uppercase urls. I use the following function:
protected void Page_Load(object sender, EventArgs e)
{
string url = Request.Url.ToString();
if (url != Request.Url.ToString().ToLower())
{
url = Request.Url.ToString().ToLower();
Response.Status = "301 Moved Permanently";
Response.AddHeader("Location", url);
}
}
Question is:
How do I change these to clean urls like /adrian_seo
I mean how do I handle requests coming to /adrian_seo and how do I show my old pages with new urls.
Do I need to use Global.asax?
Have a look into ASP.NET routing.
Use an HttpModule:
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
void context_BeginRequest(object sender, EventArgs e)
{
HttpContext context = ((HttpApplication)sender).Context;
if (context.Request.RawUrl.ToLowerInvariant().Equals("YOURSEOURL"))
context.RewritePath("YOURNONSEOURL");
}
Note that you don't want to hard code all this. Find some sort of regex to match your need, like if the SEO url is: /page/234234/This-is-my-page-title, you grab the 234234 and rewrite the path to page.aspx?pageid=234234
UPDATE
You can also use the IIS 7 Rewrite Module
I recommend using the UrlRewritingNet component. When writing your own library you need to overcome some difficulties, this library already handles that stuff for you...
It is a rewrite-module tuned for
ASP.NET 2.0, and offers support for
Themes and Masterpages
Regular Expressions
Good Postback-Urls
Cookieless Sessions
Runs in Shared-Hosting or Medium-Trust enviroments
OutputCache is supported
Redirects possible, even to other Domains
To enable extenionless urls in asp.net with IIS 6 or lower your also need to configure IIS to let asp.net handle all incoming requests.
You could use http://urlrewriter.net/ which can be used on asp.net 1.1 ->
After some Read up on Routing in Asp.net:
http://blog.eworldui.net/post/2008/04/ASPNET-MVC---Legacy-Url-Routing.aspx
Which brings both 301 redirects for SEO page rank and Asp.net Routing for permanent organic SEO solution.