Similar route mapping - asp.net-mvc

I need to map to create controller what must response to two urls:
"http://localhost/api/controller?id=1" (where only id value can change)
"http://localhost/api/controller/anotherId/someconst" (where anotherId is the only one changing part)
i map it to such route:
routes.MapHttpRoute("Test", "api/{controller}/{id}/{someconst}", new { controller = "Test", someconst = RouteParameter.Optional });
And have to methods in my controller:
public void Get(int id) { ... }
public void Get(int anotherId, string someconst ) { ... }
It works...But it doesn't look nice...cause "string someconst" is not a param, it's just a const part of url. But if i remove "string someconst" param second url wouldn't work.
Is it possible to map one controller to two routes to resolve this urls to make it clear without fake param which is a const in fact?

Well i've got the answer...just to have to routes...
routes.MapHttpRoute("Test", "api/{controller}/{id}", new { controller = "Test", action = "Get", id= #"\d+"); );
routes.MapHttpRoute("TestSomeConst", "api/{controller}/{anotherId}/someconst", new { controller = "Test", action = "GetSomeconst", anotherId= #"\d+");
And change controller methods (actions):
public void Get(int id) { ... }
public void GetSomeconst(int anotherId) { ... }

One thing you could try doing is to map the route like this:
routes.MapHttpRoute("Test", "api/{controller}/{id}/{action}", new { controller = "Test", action = "Get", id= #"\d+"} );
and make your actions:
public void Get(int id) { ... }
[HttpGet]
public void Someconst(int id) { ... }
Because your action defaults to the "Get" method, you can ignore that and call it with:
http://localhost/api/test/1
If you wanted to call your other method, you would use
http://localhost/api/test/1/someconst

Related

Redirect to specified action if requested action was not found

How can I redirect Action which is not found in controller into another action within the same controller? Let's say that file abc.txt is requested via http://localhost:5000/Link/GetFile/abc.txt. My controller correctly serving that file. But now, i need to handle request such as http://localhost:5000/Link/Document/abc. Of course there is no any action matched to Document so I need to invoke function Error within the same controller (including id from original request).
I tried to solve this with StatusCodePagesWithReExecute function but then my File action is not working (each request goes directly to Error function).
I have following controller:
public class LinkController : ControllerBase
{
public IActionResult GetFile(string id)
{
return DownloadFile(id);
}
public IActionResult Error(string id)
{
return File("~/index.html", "text/html");
}
private FileResult DownloadFile(string fileName)
{
IFileProvider provider = new PhysicalFileProvider(#mypath);
IFileInfo fileInfo = provider.GetFileInfo(fileName);
var readStream = fileInfo.CreateReadStream();
return File(readStream, "text/plain");
}
}
and startup configuration:
app.UseDefaultFiles();
app.UseStaticFiles(new StaticFileOptions
{
ServeUnknownFileTypes = true,
DefaultContentType = "application/octet-stream",
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller}/{action}/{id?}"
);
});
Any clues how to solve this problem?
Regards
You can use UseStatusCodePages to achieve a simple redirection whenever there's a 404. Here's what it looks like:
app.UseStatusCodePages(ctx =>
{
if (ctx.HttpContext.Response.StatusCode == 404)
ctx.HttpContext.Response.Redirect("/Path/To/Your/Action");
return Task.CompletedTask;
});
Just add this somewhere above UseMvc.
EDIT:
I´m sorry, my first answer was not correct.
IRouteCollection router = RouteData.Routers.OfType<IRouteCollection>().First();
with this, you can match an url to controller action
Create HttpContext for testing (example with injection)
private readonly IHttpContextFactory _httpContextFactory;
public HomeController(
IHttpContextFactory httpContextFactory)
{
_httpContextFactory = httpContextFactory;
}
Create the context with values
HttpContext context = _httpContextFactory.Create(HttpContext.Features);
context.Request.Path = "/Home/Index";
context.Request.Method = "GET";
Check route
var routeContext = new RouteContext(context);
await router.RouteAsync(routeContext);
bool exists = routeContext.Handler != null;
Further reading: https://joonasw.net/view/find-out-if-url-matches-action

C#.NET MVC Route Aliasing

I've been searching and searching for away to make old URL like we used to do in aspx pages where you could have an alias pointing to a page like www.domain.com/my-great-alias point to www.domain.com/alias.aspx. I want to do the same thing in MVC but can not figure out how to make this happen in the route table. Where www.domain.com/my-great-alias would show up to the end user as such but point to www.domain.com/alias/2
Does this make sense to anyone else what I'm looking for?
// router
routes.MapRouteLowercase(
"Alias",
"{id}",
new
{
controller = "alias",
action = "select",
id = UrlParameter.Optional
}
);
// Alias controller
public ActionResult Select()
{
return View("select");
}
// Recipe Controller
public ActionResult Select()
{
return View();
}
You should be able to do this utilizing route config and parameters (as long as it's in the same domain):
Routing
routes.MapRoute(
name: "AliasRoute",
url: "{id}",
defaults: new { controller = "Alias" }
);
Controller
public class AliasController : Controller
{
public ActionResult Index(string id)
{
//DO SOME DATABASE STUFF HERE TO LOOKUP THE CORRESPONDIND CONTROLLER AND ACTION
var controllerAction = lookupControllerActionInDatabase(id);
return View(controllerAction.ViewName);
//OR
//DO CONDITIONAL CHECKS HERE AND RETURN THE APPROPRIATE VIEW
if (id == "my-great-alias") {
return View("Alias");
} else if (id == condition1) {
return View("viewForCondition1");
} else if (id == condition2) {
return View("viewForCondition2");
}
//AND SO ON...
}
}

How to utilize a user-defined url action in asp,net mvc?

My hope is to provide a method to end users that will let them enter a value 'SmallBuildingCompany', and then use this value to make a custom url that will redirect to an informational view. so for example, www.app.com/SmallBuildingCompany. Can anyone point me to some information to help on this?
edited 161024
My attempt so far:
I added this within RouteConfig.
RouteTable.Routes.MapRoute(
"Organization",
"O/{uniqueCompanyName}",
new { controller = "Organization", action = "Info" }
and added a new controller method and view under the organization controller.
public async Task<ActionResult> Info(string uniqueCompanyName)
{
var Org = db.Organizations.Where(u => u.uniqueCompanyName == uniqueCompanyName).FirstOrDefault();
Organization organization = await db.Organizations.FindAsync(Org.OrgId);
return View("Info");
}
You can achieve this by using the SmallBuildingCompany part of the URL as a parameter for an action that is used to display every informational view.
Set up the Route in Global.asax.cs to extract the company name as parameter and pass it to the Index action of CompanyInfoController:
protected void Application_Start() {
// Sample URL: /SmallBuildingCompany
RouteTable.Routes.MapRoute(
"CompanyInfo",
"{uniqueCompanyName}",
new { controller = "CompanyInfo", action = "Index" }
);
}
Note that this Route will probably break the default route ({controller}/{action}/{id}), so maybe you want to prefix your "Info" route:
protected void Application_Start() {
// Sample URL: Info/SmallBuildingCompany
RouteTable.Routes.MapRoute(
"CompanyInfo",
"Info/{uniqueCompanyName}",
new { controller = "CompanyInfo", action = "Index" }
);
}
Then the CompanyInfoController Index action can use the uniqueCompanyName parameter to retrieve the infos from the database.
public ActionResult Index(string uniqueCompanyName) {
var company = dbContext.Companies.Single(c => c.UniqueName == uniqueCompanyName);
var infoViewModel = new CompanyInfoViewModel {
UniqueName = company.UniqueName
}
return View("Index", infoViewModel);
}
ASP.NET Routing

Url.routeUrl returns null (I've tried same questions)

Hi everyone I wanna get url like {Controller}/{action}/{postid}-{address}
but routUrl returns null please help me to solve it.(I'm newbie in MVC)
my route config is
routes.MapRoute(
name: "Post",
url: "Posts/Show/{postid}-{address}",
defaults: new { controller = "Posts", action = "Index", postid = "", address = "" }
);
and index.cshtml
#item.PostTitle
the url that generate is
http://localhost:59066/Posts/Show/1-Post-with-Featured-Image
but in PostsController
public ActionResult Show(string add)
{ return View();}
"string add" is null !
I wouldn't change the Routes...
try this...
#item.PostTitle
This will send PostId and Address as parameters, so you can get them in the controller like:
public ActionResult AwesomeThings(int PostId, String Address)
{
var foo = PostId;
var bar = Address;
return View(model);
}
No changes in routing,
Index.cshtml:
#item.PostTitle
Controller:
public ActionResult Show(string postid, string address)
{ return View();}
I changed the route to
routes.MapRoute("Post", "post/{postid}-{address}", new { controller = "Posts", action = "Show" ,postid="",address=""}, namespaces);
and added a route with same controller and action
routes.MapRoute("PostAddress", "post/{IdAndAdd}", new { controller = "Posts", action = "Show" }, namespaces);
routes.MapRoute("Post", "post/{postid}-{address}", new { controller = "Posts", action = "Show" ,postid="",address=""}, namespaces);
then action received "idAndAdd" correctly
public ActionResult Show(string idAndAdd)
{
var parts = SeperateAddress(idAndAdd);
if (parts == null)
return HttpNotFound();
var post = db.Posts.Find(parts.Item1);
if (post == null)
return HttpNotFound();
if (!post.Address.Equals(parts.Item2, StringComparison.CurrentCultureIgnoreCase))
return RedirectToRoutePermanent("Post", new { postid = parts.Item1, address = post.Address });
return View(post);
}
and it's worked .

ASPMvc Routing Issues with legacy url

I have got a legacy url that I cannot change, which is output on a page which needs to now post to a new MVC version of the page:
http://somesite.com/somepage?some-guid=xxxx-xxxx
Now I am trying to map this to a new controller but I need to get the some-guid into my controller:
public class MyController : Controller
{
[HttpGet]
public ActionResult DisplaySomething(Guid myGuid)
{
var someResult = DoSomethingWithAGuid(myGuid);
...
}
}
I can change the controller and routes as much as I like, however the legacy url cannot change. So I am a bit stumped as to how I can get access to the some-guid.
I have tried routing with the ?some-guid={myGuid} but the routing doesn't like the ?, so then I tried to let it autobind, but as it contains hyphens it doesn't seem to bind. I was wondering if there was any type of attribute I could use to hint that it should bind from a part of the querystring...
Any help would be great...
I would have thought you would have done a route a bit like this..
routes.MapRoute(
"RouteName", // Name the route
"somepage/{some-guid}", // the Url
new { controller = "MyController", action = "DisplaySomething", some-guid = UrlParameter.Optional }
);
The {some-guid} part of URL matches your url parmater and passes it to the controller.
So if you have your action like so :
public ActionResult DisplaySomething(Guid some-guid)
{
var someResult = DoSomethingWithAGuid(some-guid);
...
}
Give that a go and see how you get on..
routes.MapRoute(
"Somepage", // Route name
"simepage", // URL with parameters
new { controller = "MyController", action = "DisplaySomething"
);
And then in your controller:
public class MyController : Controller {
public ActionResult DisplaySomething(Guid myGuid)
{
var someResult = DoSomethingWithAGuid(myGuid);
...
}
}
Try this:
routes.MapRoute("SomePageRoute","Somepage",
new { controller = "MyController", action = "DisplaySomething" });
And then in your controller:
public ActionResult DisplaySomething() {
Guid sGuid = new Guid(Request.QueryString["some-guid"].ToString());
}

Resources