OK so I would love to know how to check witch routes are currently in place in my MVC app, because currently I have this setup for MVC3 app and as far as I know everything is correct, but the "Data" route still does not work:
global.asax
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using InteractiveAnalysis.Common;
using System.Data.SqlClient;
using System.Data;
using System.Configuration;
using System.Diagnostics;
using InteractiveAnalysis.App_Start;
using System.Web.Optimization;
namespace InteractiveAnalysis
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : ToolsFramework.Mvc.ToolsFrameworkHttpApplicationBase
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Excel", // Route name
"excel", // URL with parameters
new { controller = "Excel", action = "Index"} // Parameter defaults
);
routes.MapRoute(
"Data", // Route name
"data", // URL with parameters
new { controller = "Data", action = "Index" } // Parameter defaults
);
routes.MapRoute(
"Version", // Route name
"version/{action}", // URL with parameters
new { controller = "Version", action = "Index" } // Parameter defaults
);
routes.MapRoute(
"Main", // Route name
"{ver}", // URL with parameters
new { controller = "Main", action = "Index", ver = UrlParameter.Optional } // Parameter defaults
);
/*
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("cache/{action}/{id}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Main", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
*/
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
UnityObject.Register();
ToolsFramework.Cache.OutputCacheHandeler.addCacheKey(UnityObject.APPLICATION_NAME);
//OldBundleConfig.RegisterBundles(BundleTable.Bundles);
}
protected void Application_Error(object sender, EventArgs e)
{
Response.Clear();
Exception exception = Server.GetLastError();
HttpException httpException = (exception.GetBaseException() as HttpException);
if (httpException != null)
{
switch (httpException.GetHttpCode())
{
case 501: //function not implemented
Server.ClearError();
Response.Write(exception.Message);
return;
}
}
#if !DEBUG
if (Euroland.Azure.Utilities.AzureEnvironment.IsAvailable)
{
EventLog.WriteEntry(InteractiveAnalysis.Common.UnityObject.APPLICATION_NAME, "Error:\r\n\r\n" + exception.Message + "\r\n\r\nStack Trace:\r\n" + exception.StackTrace, EventLogEntryType.Error);
}
else
{
Exception exx = Server.GetLastError().GetBaseException();
System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(exx, true);
string Category = "ASP.NET error";
string ASPCode = "N/A";
string ASPDescription = exx.ToString();
if (ASPDescription.Length > 500) { ASPDescription = ASPDescription.Substring(0, 500); }
string Column = trace.GetFrame(0).GetFileColumnNumber().ToString();
string Description = exx.Message.ToString();
if (Description.Length > 500) { Description = Description.Substring(0, 500); }
string File = trace.GetFrame(0).GetFileName();
string Line = trace.GetFrame(0).GetFileLineNumber().ToString();
string Number = "N/A";
string Source = trace.GetFrame(0).GetMethod().Name;
if (Source.Length > 500) { Source = Source.Substring(0, 250); }
string ServerName = HttpContext.Current.Server.MachineName; //Request.ServerVariables["SERVER_NAME"];
string ServerIP = Request.ServerVariables["LOCAL_ADDR"];
string RemoteIP = Request.ServerVariables["REMOTE_ADDR"];
string UserAgent = Request.ServerVariables["HTTP_USER_AGENT"];
string Referer = Request.ServerVariables["REFERER"];
string URL = Request.Url.ToString();
//currently it can function in the local enviroment
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocaleErrorConnectionString"].ToString());
SqlCommand myCommand = new SqlCommand();
myCommand.CommandType = CommandType.StoredProcedure;
myCommand.CommandText = "spInsertServerError";
myCommand.Connection = conn;
myCommand.Parameters.AddWithValue("#Category", Category);
myCommand.Parameters.AddWithValue("#ASPCode", ASPCode);
myCommand.Parameters.AddWithValue("#ASPDescription", ASPDescription);
myCommand.Parameters.AddWithValue("#Column", Column);
myCommand.Parameters.AddWithValue("#Description", Description);
myCommand.Parameters.AddWithValue("#File", File);
myCommand.Parameters.AddWithValue("#Line", Line);
myCommand.Parameters.AddWithValue("#Number", Number);
myCommand.Parameters.AddWithValue("#Source", Source);
myCommand.Parameters.AddWithValue("#ServerName", ServerName);
myCommand.Parameters.AddWithValue("#ServerIP", ServerIP);
myCommand.Parameters.AddWithValue("#RemoteIP", RemoteIP);
myCommand.Parameters.AddWithValue("#UserAgent", UserAgent);
myCommand.Parameters.AddWithValue("#Referer", Referer);
myCommand.Parameters.AddWithValue("#URL", URL);
try
{
conn.Open();
myCommand.ExecuteNonQuery();
}
catch { }
finally
{
if (conn.State != ConnectionState.Closed) { conn.Close(); }
//Server.ClearError();
}
}
#endif
}
}
}
DataController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Text;
using System.Globalization;
using InteractiveAnalysis.Models;
using ToolsFramework;
namespace InteractiveAnalysis.Controllers
{
public class DataController : Controller
{
//
// GET: /Data/
public string Index()
{
return "something";
}
}
}
But every time I check "localhost:62570/data/" I get a 404 and I just do not get it. What am I missing why hasn't the "Data" route taken hold? As far as I know I have done everything correctly.
The best and easiest way to check/debug routes is using the Phil Haack's route debugger, you can install it with following nuget package
Related
I Implement a web site with ASP.net MVC . it works fine in offline. but after uploading project on my Godaddy host, the URL changed.
My host in Godaddy is somehow that it supprts diffrent domains on one host. there is a website in my root and some folders for other websites. a structre is like below
I drag whole project to the folder test. suppose my domain is www.example.com and I Create a folder named test, and then attached the www.example.com to the \test folder. the problem is while I type www.exmple.com in the browser, then press enter, the URL change to 'www.example.com/test/en'( the 'en' is the name of my view) but the problem is that I do not want to have name of my folder(test) in the URL.
I am not sure if the problem is in my side or Godaddy , but here is my route config which it works exactly what I need in offline .
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
and here is my controller:
public class HomeController : Controller
{
public async Task<ActionResult> Index()
{
try
{
string userIpAddress = this.Request.UserHostAddress;
//string userIpAddress = "2.63.255.255";
var client = new HttpClient
{
BaseAddress = new Uri("http://freegeoip.net/xml/")
};
var response = await client.GetAsync(userIpAddress);
var content = await response.Content.ReadAsStringAsync();
var result = (Response)new XmlSerializer(typeof(Response)).Deserialize(new StringReader(content));
var country_name = result.CountryName;
var country_code = result.CountryCode;
TempData["Country_code"] = country_code;
TempData["Country_name"] = country_name;
if (country_code == "FR")
{
return RedirectToAction("en", "Home");
}
else if (country_code == "JP")
{
return RedirectToAction("en", "Home");
}
else if (country_code == "DE")
{
return RedirectToAction("en", "Home");
}
else
{
return RedirectToAction("en", "Home");
}
}
catch
{
return RedirectToAction("en", "Home");
}
}
public ActionResult en()
{
return View();
}
}
I want URL just change to www.example.com/en insted of www.example.com/test/en
Appreciate any help.
I have this ASP.NET MVC 5 project which I'm converting over to AngularJS with MS Web Api.
Now in the old project I have these c# controllers of type Controller, however in my new project I've created some new Web Api controllers of type ApiController.
Now I'd like to reuse the old controller code in my new project. Herein lies my confusion.
As I attempt to port the old controller code over to my Web Api controller, I'm getting some front-end $http request errors.
Here's a function from my Angular dataService factory which makes an http req down to 'api/Whatif/SummaryPortfolios':
function getCurrPortfoliosLIst() {
var deferred = $q.defer();
var url = 'api/Whatif/SummaryPortfolios';
var req={
method: 'POST',
url: url,
headers: {
'Content-Type': 'application/json',
},
data:{}
};
$http(req).then(function (resp){
deferred.resolve(resp.data);
}, function(err){
console.log('Error from dataService: ' + resp);
});
}
But the $http error section is returning this exception:
data: Object
ExceptionMessage: "Multiple actions were found that match the request:
↵SummaryPortfolios on type MarginWorkbenchNG.Controllers.WhatifController
↵Post on type MarginWorkbenchNG.Controllers.WhatifController"
ExceptionType: "System.InvalidOperationException"
Message: "An error has occurred."
StackTrace: " at System.Web.Http.Controllers.ApiControllerActionSelector.ActionSelectorCacheItem.SelectAction(HttpControllerContext controllerContext)
↵ at System.Web.Http.Controllers.ApiControllerActionSelector.SelectAction(HttpControllerContext controllerContext)
↵ at System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
↵ at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()
Here's the c# API controller I'm calling down to, but I need to figure out how to create methods other than straight Get() and Post() methods:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
using Microsoft.AspNet.Identity;
using NLog;
using Microsoft.AspNet.Identity.Owin;
using MarginWorkbenchNG.Models;
using Rz.DAL;
using Rz.DAL.Integration;
using Rz.DAL.Models;
using Rz.DAL.Models.Rz;
namespace MarginWorkbenchNG.Controllers
{
public class WhatifController : ApiController
{
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
[HttpPost]
public List<WhatifSummaryViewModel> SummaryPortfolios(string filterValue = "", int? whatIfBatchNumber = null, bool includeBaseline = true)
{
// Get portfolios from Rz
IEnumerable<Portfolio> portfolios = GetPortfolios(filterValue, whatIfBatchNumber, includeBaseline)
.Where(x => x.PortfolioKeys.Any(k => k.Type == Settings.Whatif.SidebarPortfolioKey && k.DisplayValue == filterValue));
// View Model
List<WhatifSummaryViewModel> model = new List<WhatifSummaryViewModel> { };
/// additional code here...
return model;
}
}
}
The old controller (from the MVC5 project) looks slightly different of course because the _Summary method is of type ActionResult and returns a Partial:
public class WhatifController : Controller
{
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult _Summary(string filterValue = "", int? whatIfBatchNumber = null, bool includeBaseline = true)
{
// Get portfolios from Razor
IEnumerable<Portfolio> portfolios = GetPortfolios(filterValue, whatIfBatchNumber, includeBaseline)
.Where(x => x.PortfolioKeys.Any(k => k.Type == Settings.Whatif.SidebarPortfolioKey && k.DisplayValue == filterValue));
// View Model
List<WhatifSummaryViewModel> model = new List<WhatifSummaryViewModel> { };
// additional code removed for brevity...
return PartialView(model.OrderBy(x => x.Title).ThenBy(x => x.SubTitle));
}
My RouteConfig.cs :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace MarginWorkbenchNG
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
The old project also uses Html forms to pull the URL, for example:
<form id="whatif-summary-form" action="#Url.Action("_Summary", "WhatIf")" method="POST"></form>
and then pulls the action attrib to get the URL when building out the ajax request in JavaScript (non-Angular) :
url: form.prop("action")
Is this your entire ApiController? The error message you are receiving is because your ApiController has several methods that are of the same type and it can't tell which one to route to. To test this: comment out all of your controller's methods except the one you are calling. You shouldn't receive that error anymore.
This is an easy fix, just tell web api how to map your route. Add the attribute '[Route("yourroute')]' to your method and it should work.
public class WhatifController : ApiController
{
[HttpPost, Route("Your Route Goes here 'SummaryPortfolios'")]
public IHttpActionResult SummaryPortfolios(string filterValue = "", int? whatIfBatchNumber = null, bool includeBaseline = true)
{
// Get portfolios from Rz
IEnumerable<Portfolio> portfolios = GetPortfolios(filterValue, whatIfBatchNumber, includeBaseline)
.Where(x => x.PortfolioKeys.Any(k => k.Type == Settings.Whatif.SidebarPortfolioKey && k.DisplayValue == filterValue));
// View Model
List<WhatifSummaryViewModel> model = new List<WhatifSummaryViewModel> { };
/// additional code here...
return Ok(model);
}
}
i try to create web application with highchart and this is my tutorial http://csharptrenches.wordpress.com/2013/08/21/how-to-use-highcharts-js-with-asp-net-mvc-4/ .Code in my controller and view not have some error.but i have some problem when i'm run a browser ,it's tell me about The resource can not be found .Can you tell me why and how can i do in this case. Thank you so much.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DotNet.Highcharts;
using DotNet.Highcharts.Helpers;
using DotNet.Highcharts.Options;
using DotNet.Highcharts.Enums;
namespace HighCharts.Controllers
{
public class TransactionCount
{
public string MonthName { get; set; }
public int Count { get; set; }
}
public class IndexController : Controller
{
//
// GET: /Index/
public ActionResult Index()
{
var transaction = new List<TransactionCount> {
new TransactionCount(){ MonthName="January", Count=40},
new TransactionCount(){ MonthName="February", Count=20},
new TransactionCount(){ MonthName="March", Count=35},
new TransactionCount(){ MonthName="April", Count=70}
};
//change mountName & value to array
var xDataMonths = transaction.Select(i => i.MonthName).ToArray();
var yDataValue = transaction.Select(i => new object[] {i.Count}).ToArray();
var chart = new Highcharts("chart")
//choose type of graph
.InitChart(new Chart { DefaultSeriesType = ChartTypes.Column })
//set a title
.SetTitle(new Title { Text = "financial" })
//sub title
.SetSubtitle(new Subtitle { Text = "Accounting" })
//load value to xAxis
.SetXAxis(new XAxis { Categories = xDataMonths })
//set the y title and format text
.SetYAxis(new YAxis { Title = new YAxisTitle { Text = "Values" } })
.SetTooltip(new Tooltip
{
Enabled = true,
Formatter = #"function() { return '<b>'+ this.series.name +'</b><br />'+this.x +': '+ this.y:}"
})
.SetPlotOptions(new PlotOptions
{
Column = new PlotOptionsColumn
{
DataLabels = new PlotOptionsColumnDataLabels
{
Enabled = true
},
EnableMouseTracking = false
}
})
//load data value to yAxis
.SetSeries(new[]{
new Series {Name = "Per Month", Data = new Data(yDataValue)}
});
return View(chart);
}
}
}
and this is my View
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#model DotNet.Highcharts.Highcharts
<p>My Column Chart</p>
#(Model)
And this is my route config
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace HighCharts
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "IndexController", action = "ShowChart", id = UrlParameter.Optional }
);
}
}
}
The Problem is inside route config
Change
defaults: new { controller = "IndexController", action = "ShowChart", id = UrlParameter.Optional });
To
defaults: new { controller = "Index", action = "Index", id = UrlParameter.Optional });
Your controller does not has an action named ShowChart as what you provide in your codes, and for controller parameter you only need to write the actionName.
I am using this example for MVC:
http://www.asp.net/mvc/tutorials/mvc-4/aspnet-mvc-4-mobile-features
When I deploy the site, it looks fine on my Windows Phone. When I visit my site in an iPad, I see no jQuery mobile. How do I enable tablet support?
I had to add iPad as a registered device. Here is my global.asax
using System;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using System.Web.WebPages;
using MvcMobile;
using System.Web.Http;
using System.Collections.Generic;
using System.Web;
using System.Linq;
namespace JMA.Web
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
protected void Application_Start()
{
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
BundleMobileConfig.RegisterBundles(BundleTable.Bundles);
RegisterCustomDisplayModes();
}
private void RegisterCustomDisplayModes()
{
Dictionary<string, Func<HttpContextBase, bool>> displayModes = new Dictionary<string, Func<HttpContextBase, bool>>
{
{"Mobile", c => c.Request.UserAgent.IndexOf("iPad", StringComparison.InvariantCultureIgnoreCase) > 0}
};
displayModes.Keys.ToList().ForEach(
key => DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode(key)
{
ContextCondition = c =>
{
if (c == null || c.Request == null || string.IsNullOrEmpty(c.Request.UserAgent))
{
return false;
}
return displayModes[key](c);
}
}));
}
}
}
The word mobile redirects users to Shared/Layout/_Layout.Mobile. The word iPad looks for the device. More info can be found here:
http://www.asp.net/mvc/tutorials/mvc-4/aspnet-mvc-4-mobile-features
"Browser Specific Views"
If I were to change Mobile to iPad, the browser redirects to _Layout.iPad
Go to ~/Shared/_ViewSwitcher and change the code:
#if (Request.Browser.IsMobileDevice && Request.HttpMethod == "GET" ||
Request.UserAgent.IndexOf("iPad", StringComparison.InvariantCultureIgnoreCase) > 0 )
{
<div class="view-switcher ui-bar-d" data-theme="d">
#if (ViewContext.HttpContext.GetOverriddenBrowser().IsMobileDevice || Request.UserAgent.IndexOf("iPad", StringComparison.InvariantCultureIgnoreCase) > 0 )
{
#: Displaying mobile view
#Html.ActionLink("Desktop view", "SwitchView", "ViewSwitcher", new { mobile = false, returnUrl = Request.Url.PathAndQuery }, new { rel = "external" })
}
else
{
#: Displaying desktop view
#Html.ActionLink("Mobile view", "SwitchView", "ViewSwitcher", new { mobile = true, returnUrl = Request.Url.PathAndQuery }, new { rel = "external" })
}
</div>
}
I am new to asp.net mvc and now struggling with url routing. I'm using asp.net mvc 3 RC2.
How can I create a url routing that IGNORES the very end extension in url. the extension can be: .html, .aspx, .php, .anything.
For example, these urls:
/Home.html
/Home.en
/Home.fr
/Home
should go to Home controller?
one more example:
/Home/About.html
/Home/About.en
/Home/About.fr
/Home/About
should go to Home controller and About action.
thank you :)
I'm not sure if you're using IIS7, but if so, then I would recommend a rewrite rule which checks for urls ending in .xyz and then doing a rewrites for them without the .xyz.
Something like this:
<rewrite>
<rules>
<rule name="HtmlRewrite">
<match url="(.*)(\.\w+)$" />
<action type="Rewrite" url="{R:1}" />
</rule>
</rules>
</rewrite>
This will handle the use cases you suggested. Anything that ends with an extension and some characters will be rewritten to a url without the extension. The benefit of this is that you will only need one route because everything goes into your application without one.
You just need to tweak the default route in Global.asax.cs, try this:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}.{extension}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
The {extension} value from the url will be included in the route data, but you can just safely ignore it if you don't need it
Either create your own route class, or use this regex route implementation: http://blog.sb2.fr/post/2009/01/03/Regular-Expression-MapRoute-With-ASPNET-MVC.aspx
You could handle this in IIS instead of ASP.NET MVC using IIS Url rewriting. See for example: http://learn.iis.net/page.aspx/496/iis-url-rewriting-and-aspnet-routing/
I started to work on this question as a weekend assignment :D
below code will work as requested in question. please refer below references
1] MyUrlRoute Class : RouteBase
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace MvcIgnoreUrl
{
#region //References
// SO question /http://stackoverflow.com/questions/4449449/asp-net-mvc-to-ignore-html-at-the-end-of-all-url
// Implementing Custom Base entry - Pro Asp.Net MVc Framework
//- http://books.google.com/books?id=tD3FfFcnJxYC&pg=PA251&lpg=PA251&dq=.net+RouteBase&source=bl&ots=IQhFwmGOVw&sig=0TgcFFgWyFRVpXgfGY1dIUc0VX4&hl=en&ei=z61UTMKwF4aWsgPHs7XbAg&sa=X&oi=book_result&ct=result&resnum=6&ved=0CC4Q6AEwBQ#v=onepage&q=.net%20RouteBase&f=false
// SO previous Question on ihttphandler - http://stackoverflow.com/questions/3359816/can-asp-net-routing-be-used-to-create-clean-urls-for-ashx-ihttphander-handle
// phil haack's Route Debugger http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx
#endregion
public class MyUrlRoute : RouteBase
{
public override RouteData GetRouteData(HttpContextBase httpContext)
{
//~/Account/LogOn
//~/Home.aspx - Works fine
//~/home/index.aspx -Works Fine
//http://localhost:57282/home/index/1/2/3 - Works fine
//http://localhost:57282/Account/Register http://localhost:57282/Account/LogOn - Works Fine
string url = httpContext.Request.AppRelativeCurrentExecutionFilePath;
//check null for URL
const string defaultcontrollername = "Home";
string[] spliturl = url.Split("//".ToCharArray());
string controllername = String.Empty;
string actionname = "Index";
if (spliturl.Length == 2) //for ~/home.aspx and ~/
{
if (String.IsNullOrEmpty(spliturl[1])) //TODO: http://localhost:57282/ not working - to make it working
{
controllername = defaultcontrollername;
}
else
{
controllername = spliturl[1];
if (controllername.Contains("."))
{
controllername = controllername.Substring(0, controllername.LastIndexOf("."));
}
}
}
else if (spliturl.Length == 3) // For #/home/index.aspx and /home/about
{
controllername = spliturl[1];
actionname = spliturl[2];
if (actionname.Contains("."))
{
actionname = actionname.Substring(0, actionname.LastIndexOf("."));
}
}
else //final block in final case sned it to Home Controller
{
controllername = defaultcontrollername;
}
RouteData rd = new RouteData(this, new MvcRouteHandler());
rd.Values.Add("controller", controllername);
rd.Values.Add("action", actionname);
rd.Values.Add("url", url);
return rd;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
return null;
}
}
}
in global.asax.cs add below code
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add(new MyUrlRoute()); // Add before your default Routes
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
working as expected.
possibly you can improve if/elseif code.
Using the Application_BeginRequest, will allow you to intercept all incoming requests, and allow you to trim the extension. Make sure to ignore requests for your content, such as .css, .js, .jpg, etc. Otherwise those requests will have their extensions trimmed as well.
protected void Application_BeginRequest(object sender, EventArgs e)
{
String originalPath = HttpContext.Current.Request.Url.AbsolutePath;
//Ignore content files (e.g. .css, .js, .jpg, .png, etc.)
if (!Regex.Match(originalPath, "^/[cC]ontent").Success)
{
//Search for a file extension (1 - 5 charaters long)
Match match = Regex.Match(originalPath, "\\.[a-zA-Z0-9]{1,5}$");
if (match.Success)
{
String modifiedPath = String.Format("~{0}", originalPath.Replace(match.Value, String.Empty));
HttpContext.Current.RewritePath(modifiedPath);
}
}
}
If you are using IIS 7, you should look at Dan Atkinson's answer.
I'm using IIS 6, so, in my case, I have the option to install isapi rewrite for IIS 6 or create custom route. I prefer to create my simple custom route class
AndraRoute.cs
// extend Route class,
// so that we can manipulate original RouteData
// by overriding method GetRouteDate
public class AndraRoute : Route
{
// constructor
public AndraRoute(
string url,
RouteValueDictionary defaults,
RouteValueDictionary constraints,
IRouteHandler routeHandler)
: base(url, defaults, constraints, routeHandler)
{
}
// get original RouteData
// check if any route data value has extension '.html' or '.anything'
// remove the extension
public override RouteData GetRouteData(HttpContextBase httpContext)
{
var data = base.GetRouteData(httpContext);
if (data == null) return null;
// from original route data, check
foreach (var pair in data.Values)
{
if (pair.Value.ToString().Contains('.'))
{
var splits = pair.Value.ToString().Split('.');
if (splits[1] == "html" || splits[1] == "anything")
{
data.Values[pair.Key] = splits[0];
}
break;
}
}
return data;
}
}
RouteCollectionExtensionHelper.cs
public static class RouteCollectionExtensionHelper
{
public static Route MapAndraRoute(this RouteCollection routes,
string name, string url, object defaults, object constraints,
string[] namespaces)
{
if (routes == null)
{
throw new ArgumentNullException("routes");
}
if (url == null)
{
throw new ArgumentNullException("url");
}
var route = new AndraRoute(url,
new RouteValueDictionary(defaults),
new RouteValueDictionary(constraints),
new MvcRouteHandler());
if ((namespaces != null) && (namespaces.Length > 0))
{
route.DataTokens = new RouteValueDictionary();
route.DataTokens["Namespaces"] = namespaces;
}
routes.Add(name, route);
return route;
}
}
RegisterRoutes method in Global.asax
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("Content/{*pathInfo}");
routes.MapAndraRoute(
"Product",
"product/{id}/{slug}",
new { controller = "product", action = "detail" },
null, null
);
routes.MapAndraRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "home", action = "index", id = UrlParameter.Optional },
null, null
);
}