i am trying to create a stackoverflow like url.
I the following example works fine. But if i remove the controller then it errors out.
http://localhost:12719/Thread/Thread/500/slug-url-text
Note the first Thread is the controller the second is the action.
How can i make the above URL look like the following excluding the controller name from the url?
http://localhost:12719/Thread/500/slug-url-text
My Routes
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("Default", // Route name
"{controller}/{action}/{id}/{ignoreThisBit}",
new
{
controller = "Home",
action = "Index",
id = "",
ignoreThisBit = ""
}); // Parameter defaults )
}
}
Thread Controller
public class ThreadController : Controller
{
//
// GET: /Thread/
public ActionResult Index()
{
string s = URLFriendly("slug-url-text");
string url = "Thread/" + 500 + "/" + s;
return RedirectPermanent(url);
}
public ActionResult Thread(int id, string slug)
{
return View("Index");
}
}
Placing the following route before the default route definition will directly call the 'Thread' action in 'Thread' controller with the 'id' and 'slug' parameter.
routes.MapRoute(
name: "Thread",
url: "Thread/{id}/{slug}",
defaults: new { controller = "Thread", action = "Thread", slug = UrlParameter.Optional },
constraints: new { id = #"\d+" }
);
Then if you really want it to be like stackoverflow, and assume someone enters the id part and not the slug part,
public ActionResult Thread(int id, string slug)
{
if(string.IsNullOrEmpty(slug)){
slug = //Get the slug value from db with the given id
return RedirectToRoute("Thread", new {id = id, slug = slug});
}
return View();
}
hope this helps.
Related
public IActionResult Info(int id)
{
return Content(id + "");
}
Whenever I input Jan/Info/2 the browser returns me the value 0. Why is this and how can I fix this? I'm using MVC core 1.1. UrlParameter.Optional is also not present in Visual Studio for some reason it's not accessible.
app.UseMvc(routes =>
{
routes.MapRoute(
name: "Naam",
template: "{controller=Jan}/{action}/{voornaam}");
routes.MapRoute(
name: "Info",
template: "{controller=Jan}/{action}/{id}");
}
public IActionResult Naam(string voornaam)
{
return Content(voornaam);
}
Because you already have another route registration which is matching the exact pattern. As per that registration, it will read the value and assign to the voornaam parameter.
So this should work
public IActionResult Info(int voornaam)
{
return Content(voornaam + "");
}
Since you have unique names for your action method, you do not need to specify the custom routes for each action method. The default route registration will work fine.
app.UseMvc(routes =>
{
routes.MapRoute(
name: "defaultroutes",
template: "{controller}/{action=Index}/{id?}",
defaults: new { controller = "jan" });
});
Assuming your controller looks like this
public class JanController : Controller
{
public IActionResult Info(int id)
{
return Content(id + " : id");
}
public IActionResult Naam(string voornaam)
{
return Content(voornaam+ ": param value");
}
}
When you access yourSite/jan/info/123, The Info method will handle that and when you request yourSite/jan/Naam?voornaam=shyju ,the Naam method will handle that.
If you want to support url structure like yourSite/jan/Naam/shyju instead of the explicit querystring, you can specify a route pattern on that action method with attribute routing
public class JanController : Controller
{
public IActionResult Info(int id)
{
return Content(id + " id");
}
[Route("[controller]/[action]/{voornaam}")]
public IActionResult Naam(string voornaam)
{
return Content(voornaam + " : param value");
}
}
Now when you request yourSite/jan/Naam/shyju, The Naam method will be called and the string "shyju" will be available in the voornaam parameter
I'm working on building a MVC4 web app and want to set specific URL I would like to use in the start point of my web application.
So I changed some values in RouteConfig.cs like this below.
routes.MapRoute(
name: "Default",
url: "{action}.mon/{id}",
defaults: new { controller = "login", action = "index", id = UrlParameter.Optional }
);
you may notify this, but I put a suffix after action name, so that I could invoke a controller, displaying the URL like " index.mon "
if I manually put "index.mon" after host address in URL bar, then it works just okay.
But when the app gets started automatically, it throws 403.14 error. ( "automatically start" means here that I ran this app by putting F5 key to run a temporary IIS server. )
the login controller looks like this
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.OleDb;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Monarch815MVC.Controllers
{
public class loginController : Controller
{
//
// GET: /login/
public ActionResult index()
{
return View();
}
public ActionResult loginProcess(string id = "000000", string pass = "example", string scode = "co")
{
Dictionary<string, object> sessionData = null;
String SqlCommand = "USP_LOGIN";
DataSet UserInfo = dataController.ExecuteDataset(dataController.CONN_STRING, CommandType.StoredProcedure, SqlCommand, arParms);
if (UserInfo.Tables[0].Rows.Count > 0)
{
sessionData = new Dictionary<string, object>();
for (int i = 0; UserInfo.Tables[0].Rows[0].Table.Columns.Count > i; i++)
{
sessionData.Add(UserInfo.Tables[0].Rows[0].Table.Columns[i].Caption, UserInfo.Tables[0].Rows[0].ItemArray[i]);
}
}
return View();
}
}
}
( let's forget about the loginProcess, I took off a few codes. )
Do I have to do something on returning phase in index() or on Web.config? or, RouteConfig.cs?
I have to use the suffix ".mon" to invoke controllers with it.
I could think of solving this issue by only using a hack. You might want to create a dummy action which will be the default action and upon being hit will redirect the request to your index.mon
i tried following, Please check if this helps you. Thanks.
In the route config
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "DefaultY",
url: "{action}-mon/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "DefaultX2",
url: "{action}/{id}",
defaults: new { controller = "Home", action = "Startup", id = UrlParameter.Optional }
);
}
In controller
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Startup()
{
return RedirectToRoute("DefaultY", new {controller = "Home", action = "Index" });
}
}
For me i used index-mon. index.mon was not working (something which i'l explore later, perhaps it relates to static files), but above code demonstrates the approach.
Hope that helps.
I'm having trouble getting ASP.net MVC to serve up the default controllers index view for the root site url http://mysite:8080/. All I get back is a 404 with The resource cannot be found. It works fine if I specify the full route path in the url : http://mysite:8080/Default/Index, however, I want the default route to apply even if the user doesn't specify the route path though. It seems that this should just work out of the gate. This is a fresh project from the VS2013 MVC 4 template.
I've tried both route mappings below and neither seems to work. How can this be achieved?
routes.MapRoute(
"Root",
"",
new { controller = "DefaultController", action = "Index" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "DefaultController", action = "Index", id = UrlParameter.Optional }
);
Here is a solution to this problem. It's disappointing that the default route's defaults do not apply for the root site url though.
routes.Add(new Route("", new SiteRootRouteHandler("~/Default/Index")));
public class SiteRootRouteHandler : IRouteHandler
{
private readonly string _redirectUrl;
public SiteRootRouteHandler(string redirectUrl)
{
_redirectUrl = redirectUrl;
}
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new SiteRootHandler(_redirectUrl);
}
}
public class SiteRootHandler: IHttpHandler
{
private readonly string _redirectUrl;
public SiteRootHandler(string redirectUrl)
{
_redirectUrl = redirectUrl;
}
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
context.Response.RedirectPermanent(_redirectUrl);
}
}
I have this Controller :
public class ProfileController : Controller
{
public ActionResult Index( long? userkey )
{
...
}
public ActionResult Index( string username )
{
...
}
}
how can i define MapRoute for this actions work like this:
mysite.com/Profile/8293378324043043840
this must be go to first action
mysite.com/Profile/MyUserName
this must be go to second action
I have this route for the first action
routes.MapRoute( name: "Profile" , url: "Profile/{userkey}" , defaults: new { controller = "Profile" , action = "Index" } );
do i need add another MapRoute ? or can i change the current MapRoute for both action?
First you cannot overload controller actions if you are using the same Http Verb (in your case GET) because you need to have unique action names.
So you need to name your actions differently:
public class ProfileController : Controller
{
public ActionResult IndexKey( long? userkey )
{
...
}
public ActionResult IndexName( string username )
{
...
}
}
Or you can use the ActionNameAttribute to give different names to your actions:
public class ProfileController : Controller
{
[ActionName("IndexKey")]
public ActionResult Index( long? userkey )
{
...
}
[ActionName("IndexName")]
public ActionResult Index( string username )
{
...
}
}
Then you will need two routes with using route constraints on the userkey to be a numeric value to setup your actions:
routes.MapRoute(name: "Profile", url: "Profile/{userkey}",
defaults: new { controller = "Profile", action = "IndexKey" },
constraints: new { userkey = #"\d*"});
routes.MapRoute(name: "ProfileName", url: "Profile/{userName}",
defaults: new {controller = "Profile", action = "IndexName"});
In ASP.NET MVC, we have #Url.Action for actions. Is there something similar like #Url.Api which would route to /api/controller?
The ApiController has a property called Url which is of type System.Web.Http.Routing.UrlHelper which allows you to construct urls for api controllers.
Example:
public class ValuesController : ApiController
{
// GET /api/values
public IEnumerable<string> Get()
{
// returns /api/values/123
string url = Url.Route("DefaultApi", new { controller = "values", id = "123" });
return new string[] { "value1", "value2" };
}
// GET /api/values/5
public string Get(int id)
{
return "value";
}
...
}
This UrlHelper doesn't exist neither in your views nor in the standard controllers.
UPDATE:
And in order to do routing outside of an ApiController you could do the following:
public class HomeController : Controller
{
public ActionResult Index()
{
string url = Url.RouteUrl(
"DefaultApi",
new { httproute = "", controller = "values", id = "123" }
);
return View();
}
}
or inside a view:
<script type="text/javascript">
var url = '#Url.RouteUrl("DefaultApi", new { httproute = "", controller = "values", id = "123" })';
$.ajax({
url: url,
type: 'GET',
success: function(result) {
// ...
}
});
</script>
Notice the httproute = "" route token which is important.
Obviously this assumes that your Api route is called DefaultApi in your RegisterRoutes method in Global.asax:
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
It works with the simpler form of Url.Action thus you don't have to reference any Routing names:
Url.Action("ActionName", "ControllerName", new { httproute = "DefaultApi" })
You might want to add an area = "" if the URL is needed within an Area. (Api controllers are outside of Areas by default.) I'm using MVC 4.
Want to be able to generate links in a typesafe manner, without hardcoded strings (controller names)?
There's a nuget for that! (and it's written by Mark Seeman)
https://github.com/ploeh/Hyprlinkr
Works like this:
Routes, as usual:
name: "API Default",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
Get an URL:
var linker = new RouteLinker(request);
var uri = linker.GetUri<FooController>(r => r.GetById(1337));
Result:
http://localhost/api/foo/1337
Here is the KISS method for answering the question:
If this is the code that you would use to create a MVC controller URL
#Url.Action("Edit", "MyController")
In order to get a URL for the API version of the controller (assuming you use the same controller name) you can use
#Url.Action("Edit", "api/MyController")
All the Url.Action method is doing is appending the root path of the application, with the controller name, followed by the action name (unless it is "Index" in which case it is not appended. if the route values object has an id property the value is also appended to the URL.