Route from aspx code behind to MCV controller - asp.net

I'm creating a hybrid aspx/mvc application and want to route from the aspx code behind to an mvc controller. I am missing something... To keep this simple: I have a button in my aspx page:
<asp:Button ID="Attendees" runat="server" OnClick="Attendees_Click"/>
to my code behind:
protected void Attendees_Click(object sender, EventArgs e)
{
//How can this be redirected this to my Attendee/Index Controller?
//Url.Redirect("Index","Attendee");//This does not work?
Response.Redirect();
}

Usually by mentioning the path of controller name and action name should work:
Response.Redirect("~/Attendee/Index");
However if the above way doesn't work, the best way is using UrlHelper instance to create target URL (with UrlHelper.Action() overload) and redirect afterwards:
var url = new UrlHelper(HttpContext.Current.Request.RequestContext);
Response.Redirect(url.Action("Index", "Attendee"));

Related

How to ignore some route while using ASP.NET Friendly URLs?

I am using ASP.NET Friendly URLs with success, but I need to ignore route for a particular Foo.aspx page (because this page needs POST data and once re-routed the POST data is not available anymore in Page_Load()!).
It looks like using ASP.NET Friendly URLs discard any attempt to ignore a route. Even the MSDN example for ignoring route doesn't work once ASP.NET Friendly URLs routing is used:
routes.Ignore("{*allaspx}", new {allaspx=#".*\.aspx(/.*)?"});
And to ignore route to Foo.aspx the code should look like that, isn't it?
routes.Ignore("{*fooaspx}", new { fooaspx = #"(.*/)?foo.aspx(/.*)?" });
The Global.asax code looks like:
public static void RegisterRoutes(RouteCollection routes) {
// This doesn't work whether I put this code before or after ASP.NET Friendly URLs code.
routes.Ignore("{*allaspx}", new { allaspx = #".*\.aspx(/.*)?" });
routes.Canonicalize().Lowercase();
var settings = new FriendlyUrlSettings();
settings.AutoRedirectMode = RedirectMode.Permanent;
routes.EnableFriendlyUrls(settings);
}
void Application_Start(object sender, EventArgs e) {
RegisterRoutes(RouteTable.Routes);
}
This question has been asked on the ASP.NET Friendly URLs codeplex site, but didn't get an answer.
Thanks for your help on this :)
Thanks to Damian Edwards comment, I got this issue completely solved, thanks Damian.
I just need to derive from WebFormsFriendlyUrlResolver to override the method ConvertToFriendlyUrl() to make it no-op when the url match the url I don't want to redirect:
using Microsoft.AspNet.FriendlyUrls.Resolvers;
public class MyWebFormsFriendlyUrlResolver : WebFormsFriendlyUrlResolver {
public MyWebFormsFriendlyUrlResolver() { }
public override string ConvertToFriendlyUrl(string path) {
if (!string.IsNullOrEmpty(path)) {
if (path.ToLower().Contains("foo")) { // Here the filter code
return path;
}
}
return base.ConvertToFriendlyUrl(path);
}
}
Then in Global.asax the code now looks like:
public static void RegisterRoutes(RouteCollection routes) {
routes.Canonicalize().Lowercase();
var settings = new FriendlyUrlSettings();
settings.AutoRedirectMode = RedirectMode.Permanent;
routes.EnableFriendlyUrls(settings,
new IFriendlyUrlResolver[] {
new MyWebFormsFriendlyUrlResolver() });
}
void Application_Start(object sender, EventArgs e) {
RegisterRoutes(RouteTable.Routes);
}
This was interesting - had to tinker :) In my comment above, what I was trying to say was "no need to ignore".
I was "right" and "wrong".
right: no need to ignore
wrong: not because of what I stated (re: physical file), but rather, by not invoking the redirect in the first place.
This will bomb out (redirect will occur, POST data is lost):
<asp:Button ID="btn1" runat="server" Text="Go" PostBackUrl="~/Target.aspx" />
This will be good (you will get POST data, no redirect occurs):
<asp:Button ID="btn1" runat="server" Text="Go" PostBackUrl="~/Target" />
The difference? I'm not asking FriendlyUrls to "re-route" anything in the 2nd option. In the first option, I'm asking for an "aspx" file, so FriendlUrls will dutifully do its purpose for being and "handle" it (and do a permanent redirect to a "friendly url" which is a GET and there goes all the POSTed data).
Inspect request in 1st option (target.aspx):
Inspect request in 2nd option (extensionless, target):
This was a clue:
var settings = new FriendlyUrlSettings();
settings.AutoRedirectMode = RedirectMode.Permanent;
And it does what it says, "do a permanent redirect" (to a "friendly url")...when "necessary" (if an "aspx" file is requested). You can tinker with this with any page in your WebForms site
if you request foo.aspx you will see a Redirect (to foo)
if you request foo, no Redirect
You can also comment out
settings.AutoRedirectMode = RedirectMode.Permanent;
and things will work but sort of defeats the purpose of FriendlyUrls...
Thinking about it, it makes perfect sense. There is no need to "redirect" on every request (ugh for performance), rather only if/when necessary...
Hth....

Custom Url Rewriting in asp.net

can anyone please provide me the details how we can implement custom URL rewriting in asp.net
My current url is look like below :
www.domainname.com/News/default.aspx?newstitle=todays latest news
And now I would like to redirect to below url :
www.domainname.com/News/todays-latest-news
Please suggest me how we can achieve the same.
Add this to global.asax
using System.Web.Routing; //top of the page
protected void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
}
void RegisterRoutes(RouteCollection routes)
{
routes.MapPageRoute("", "news/{news}", "~/news/default.aspx");
}
And then you can get the news title in default.aspx like below:
protected void Page_Load(object sender, EventArgs e)
{
if (this.RouteData.Values.Count > 0)
{
string newstitle = this.RouteData.Values[0].ToString();
}
}
to achieve your task use the concept called asp.net routing ,
here is the few examples refer for better understanding
http://www.codeproject.com/Articles/77199/URL-Routing-with-ASP-NET-4-0
http://msdn.microsoft.com/en-us/library/cc668201%28v=vs.100%29.aspx
You can use URLRewriter.Net for this purpose. It's very easy to integrate into asp.net project and also it's open source . Add the dll file of urlRewriter.Net into your project and set the rewriting rule in your web.config file. Although be careful when using it with ajax postback pages. In Raw url if you get ajax postback problem .

extending ASP.NET Page using MasterPage attributes as properties

I have an authentication roles-based system: different roles are redirected to different folders and in each folder there is a web.config that allows the access only to a particular username.
Few roles have the default page in common with a gridview that react in different ways depending on the role(different columns are shown, events trigger different methods, etc.).
so my problem is that everytime I need to make minor changes to a page I need to copy/paste the same changes to all the others default pages in the other folders.
In terms of code I solved by creating a DefaultFather class which extends System.Web.UI.Page and every other Default class inherits from DefaultFather. In this way, if I dont declare a Page-life-method, the DefaultFather method will be triggered.
but what about the graphic part(html, javascript, asp components, etc...)??
I created a NestedMasterPage just for the Default pages but everytime I need to change the appearance/behaviour of controls(gridview, buttons, linkbuttons) I must use the FindControl() method.
there isnt really another way to solve this problem?
Im thinking of using the Page_Load() method to search for each control with FindControl() and save them into attributes for later usage but it doesnt really look like a good solution.
It would be nice if I could use the masterpage components as properties but I think that in order to do that I should create public properties and I dont know if it will cause some kind of security problem.
any suggestion?
btw, if masterpage is the solution, should I remove the DefaultFather class and place the code directly into the masterpage? or is it a good idea to have another class just for the code?
I'd say there's nothing wrong with having both a master page and a base class for your page. They serve different purposes. The master page is generally all about layout, and the base class would be about page functionality.
If you want to manipulate the markup on your master page, rather than accessing the fields directly, I'd say create a logical function which does what you need it to do, and let the master page do it.
// Site.Master.cs
public void HideSubmitButton()
{
btnSubmit.Visible = false;
}
// Default.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
((SiteMaster)Master).HideSubmitButton();
}
I'd probably wrap that cast so you can use it more easily - that is something that would belong in your base class:
// DefaultFather.cs
protected new SiteMaster Master { get { return (SiteMaster)base.Master; } }
// Default.aspx.cs
Master.HideSubmitButton();
EDIT
Per your comment about attaching event handlers - if you need to attach events to objects that live on the master (which may not be a good idea - ideally the event handler for something living on the master lives on the master - but if you really need it) you can expose methods to do that as well, like:
// Site.Master.cs
public void AttachEventHandlerToGoButton(EventHandler eventHandler)
{
btnGo.Click += eventHandler;
}
// Default.aspx.cs
Master.AttachEventHandlerToGoButton(DoMyThing);
private void DoMyThing(object sender, EventArgs e) { }
or if you want to get fancy, write a wrapper event:
// Site.Master
<asp:Button ID="btnGo" runat="server" OnClick="btnGo_Click" />
// Site.Master.cs
public event EventHandler GoButtonClick;
protected void btnGo_Click(object sender, EventArgs e) {
if (GoButtonClick != null) {
GoButtonClick(sender, e);
}
}
// Default.aspx.cs
Master.GoButtonClick += DoMyThing;
private void DoMyThing(object sender, EventArgs e) { }
Also see my edit on the Master wrapper - you need the base. there to avoid a stack overflow.

ASP.NET requested page in Global.asax

I want to be able to globally grab a reference to the Page object that is currently being requested, so I've added a Global.asax file.
Is there any way to do this? I assume it has something to do with the Application_BeginRequest event.
You can access the current handler (the page) from global.asax, but not from any stage of the request life cycle. I.e. it is not possible in BeginRequest, but it is possible during PreRequestHandlerExecute:
void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
var page = (Context.Handler as System.Web.UI.Page);
}
Note that page might still be null, if the handler is not a page. Also, I'm not sure your approach is the correct one. Maybe you should explain in more detail what you want to attempt?
Create a class that is a subclass of Page that does what you want and use this subclass as the base type for all you pages.
public class MyPage : Page
{
//... override whatever you want, add functionality, whatever
}
All other pages:
public class Index : MyPage
{
// Automatically get new behaviour
}
You have to use http module to catch the every request for each page on your application and do whatever you want with the request.
var page = HttpContext.Current.Handler as Page
if(page != null) /// do something with page
PreRequestHandlerExecute should be fine for your purposes (if you don't fancy writing your own HttpModule, which is in fact very easy)

ASP.NET 4.0 Route expression builder inside Listview control

One of the features of ASP.NET 4.0 is Route Expression builder which allows you to set up hyperlinks like this:
<asp:HyperLink
runat="server"
NavigateUrl="<%$ RouteUrl:RouteName=productos,categoria=Cereales,id=2 %>" >Productos</asp:HyperLink>
Now I'm wondering if I can use this sort of syntax inside a ListView Control, I know is possible, but the tricky thing is that I want to genereate de route key value dynamically.
So instead to write id=2 I would like to write id=<%# Eval("CategoryID") %> .
Can I do that?, if so, how should I write it.
Thanks for your help!
I have searched and searched for an example did not find a way to handle building routes in an expression builder. I finally figured out a way to do this in a gridview, maybe you can adapt? See my post at the following address where I answered my own question: How to use routing in web forms and HyperLinkFields of a GridView
I think an asp hyperlink control will not work because the controls are built before the Eval() is called, but an anchor is just text so it works within a template field.
Not sure whether you can do it with the Route ExpressionBuilder. Instead you can give an ID to the Hyperlink object in the .aspx file:
<asp:HyperLink ID="productHyperLink" runat="server">Productos</asp:HyperLink>
And set the NavigateUrl property in the Page_Load method in the .cs file:
protected void Page_Load(object sender, EventArgs e)
{
int categoryId;
string categoryName;
// Get categoryId and categoryName from database
RouteValueDictionary values = new RouteValueDictionary {
{ "id", categoryId.ToString() },
{ "categoria", categoryName } };
VirtualPathData virtualPathData = RouteTable.Routes.GetVirtualPath(null, "productos", values);
productHyperLink.NavigateUrl = virtualPathData.VirtualPath;
}

Resources