Redirect to route without a query string - asp.net

How do I redirect to a route without getting a query string on my URL?
Route configuration...
routes.MapRoute(
name: "ApplicationStatus",
url: "join/ApplicationStatus/{applicationKey}/{characterId}",
defaults: new { controller = "Join", action = "ApplicationStatus" }
);
Controller code to redirect...
return RedirectToAction("ApplicationStatus", new {
applicationKey = applicationKey,
characterId =_sm.JoinState.CharacterId
});
Controller action method...
public ActionResult ApplicationStatus(string applicationKey, long characterId)
{
return View(new ApplicationStatus());
}
So when I am redirected from the controller the browser gives me the following url...
http://localhost/TestApp/Join/ApplicationStatus?applicationKey=xxxxxxx&characterId=nnnnnnnn
but I would like to get this...
http://localhost/TestApp/Join/ApplicationStatus/xxxxxxx/nnnnnnnn
Thanks in advance.

You should use RedirectToRoute.
Try this instead.
return RedirectToRoute("ApplicationStatus", new {
applicationKey = applicationKey,
characterId =_sm.JoinState.CharacterId
});

Related

ASP.net how to make RedirectToRouteResult() to a url configured in MapRoute()

I set a route map in RouteConfig.cs like:
routes.MapRoute(
name: "Default",
url: "prefix/{controller}/{action}",
defaults: new { controller = "MainView", action = "Index" }
);
And I want to do a redirect in MainView/Index under some situation, so I write code like below, and return it:
RedirectToRouteResult redirect = new RedirectToRouteResult(
new System.Web.Routing.RouteValueDictionary(new { action = "Home", controller = "Account"}));
I wish it would return the url like: localhost/prefix/Account/Home, but the result is localhost/Account/Home. How can I make the redirect result to be localhost/prefix/Account/Home?
Thanks!
All right, I made a stupid fault, there is [Authorize] attribute on this action, so the return url is made by this attribute. I correct this code and get the expected url.

RedirectToAction() generates wrong URL

I'm having a problem with MVC 4, and I guess it's something really trivial, but it's been bugging me for the last day and I can't seem to figure it out.
I have this url:
http://www.example.com/my-dashed-url
I have a Controller named:
public class MyDashedUrlController: Controller
{
}
I have only two Routes like this:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("my-dashed-url",
"my-dashed-url/{action}",
new { controller = "MyDashedUrl", action = "Index" });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home",
action = "Index",
id = UrlParameter.Optional }
);
I get to the index just fine. However, when I do this:
public ActionResult Index()
{
if (NoUserIsLoggedOn)
return RedirectToAction("Logon", "MyDashedUrl");
return View();
}
public ActionResult Logon()
{
Contact c = GetContact();
return View(c);
}
It doesn't redirect me to the "Logon" action properly.
It should redirect me to:
http://www.example.com/my-dashed-url/logon
but instead it tries to redirect me to:
http://www.example.com/logon
... which doesn't work (404 Not Found)
I'm missing something. Can anyone spot it? If anyone needs any more information, let me know.
And it's EVERY RedirectToAction that does the same thing in this controller. A Html.BeginForm("Logon", "MyDashedUrl") would also generate:
http://www.example.com/logon
I guess it has to do something with the Routes I defined, but I can't find the faulty one, seeing as they're all the same. If I disable all of my Routes besides the default one from MVC, the problem remains the same
Make sure that you have declared this custom route BEFORE the default one:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"my-dashed-url",
"my-dashed-url/{action}",
new { controller = "MyDashedUrl", action = "Index" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
Remember that routes are evaluated in the order you declared them. So the first route that matches a request will be used. If you declare your custom route after the default one, it is the default route that will match the request.

?Length=16 being appended to my URL in my MVC3 application

Here's the controller code:
public ActionResult AddFriend(string username)
{
//Todo: Add functionality to add a friend.
//Then redirect to that same profile.
return RedirectToAction("Detail", "Profile", username);
}
Contents of username is stapia.gutierrez, not 16 or anything like that.
When I visit the link:
http://localhost:9198/profile/friend/add/stapia.gutierrez
The above action is called because I create a route in Global.asax:
routes.MapRoute("AddFriend", // Route name
"Profile/Friend/Add/{username}", // URL with parameters
new { controller = "Profile", action = "AddFriend" } // Parameter defaults
);
After clicking the URL is shown as:
http://localhost:9198/Profile/stapia.gutierrez?Length=16
Any ideas?
You need to pass the route values like so:
return RedirectToAction("Detail", "Profile", new { username="value" });

ASP.NET MVC catch-all routing

I have read a few threads on StackOverflow about this, but cannot get it to work. I have this at the end of my RegisterRoutes in Global.asax.
routes.MapRoute(
"Profile",
"{*url}",
new { controller = "Profile", action = "Index" }
);
Basically what I'm trying to achieve is to have mydomain.com/Username point to my member profilepage. How would I have to set up my controller and RegisterRoutes in order for this to work?
Currently mydomain.com/somethingthatisnotacontrollername gets a 404-error.
Solution that works for your case but is not recommended
You have a predefined set of controllers (usually less than 10) in your application so you can put a constraint on controller name and then route everything else to user profile:
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { controller = "Home|Admin|Reports|..." }
);
routes.MapRoute(
"Profile",
"{username}/{action}",
new { controller = "Profile", action = "Details" }
);
But this will not work in case some username is the same as your controller name. It's a small possibility based on experience end empirical data, but it's not 0% chance. When username is the same as some controller it automatically means it will get handled by the first route because constraints won't fail it.
Recommended solution
The best way would be to rather have URL requests as:
www.mydomain.com/profile/username
Why do I recommend it to be this way? Becasue this will make it much simpler and cleaner and will allow to have several different profile pages:
details www.mydomain.com/profile/username
settings www.mydomain.com/profile/username/settings
messages www.mydomain.com/profile/username/messages
etc.
Route definition in this case would be like this:
routes.MapRoute(
"Profile",
"Profile/{username}/{action}",
new { controller = "Profile", action = "Details" }
);
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
having something that matches to mydomain.com/Username isn't really going to work because there is no way for the routing engine to distinguish between
mydomain.com/someusername
and
mydomain.com/controllername
What might be possible is, if your username scheme has a unique set of properties, i.e. is a sequence of 9 digits, you could define a route to check for something that looks like a username.
routes.MapRoute("",
"UserRoute",
"{username}",
new { controller = "Profile", action = "Index"},
new { {"username", #"\d{9}"}}
);
The key point tho, is that you need to provide some way for the routing engine to differentiate between a username and a standard controller action
You can find out more about constraints here
I had a requirement like this for my project. What i did was creating a route constraint like below:
public class SeoRouteConstraint : IRouteConstraint
{
public static HybridDictionary CacheRegex = new HybridDictionary();
private readonly string _matchPattern = String.Empty;
private readonly string _mustNotMatchPattern;
public SeoRouteConstraint(string matchPattern, string mustNotMatchPattern)
{
if (!string.IsNullOrEmpty(matchPattern))
{
_matchPattern = matchPattern.ToLower();
if (!CacheRegex.Contains(_matchPattern))
{
CacheRegex.Add(_matchPattern, new Regex(_matchPattern));
}
}
if (!string.IsNullOrEmpty(mustNotMatchPattern))
{
_mustNotMatchPattern = mustNotMatchPattern.ToLower();
if (!CacheRegex.Contains(_mustNotMatchPattern))
{
CacheRegex.Add(_mustNotMatchPattern, new Regex(_mustNotMatchPattern));
}
}
}
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
var matchReg = string.IsNullOrEmpty(_matchPattern) ? null : (Regex)CacheRegex[_matchPattern];
var notMatchReg = string.IsNullOrEmpty(_mustNotMatchPattern) ? null : (Regex)CacheRegex[_mustNotMatchPattern];
var paramValue = values[parameterName].ToString().ToLower();
return IsMatch(matchReg, paramValue) && !IsMatch(notMatchReg, paramValue);
}
private static bool IsMatch(Regex reg, string str)
{
return reg == null || reg.IsMatch(str);
}
}
Then in the register route method:
routes.MapRoute("",
"UserRoute",
"{username}",
new { controller = "Profile", action = "Index"},
new { username = new SeoRouteConstraint(#"\d{9}", GetAllControllersName())}
);
The method GetAllControllersName will return all the controller name in your project separated by | :
private static string _controllerNames;
private static string GetAllControllersName()
{
if (string.IsNullOrEmpty(_controllerNames))
{
var controllerNames = Assembly.GetAssembly(typeof(BaseController)).GetTypes().Where(x => typeof(Controller).IsAssignableFrom(x)).Select(x => x.Name.Replace("Controller", ""));
_controllerNames = string.Join("|", controllerNames);
}
return _controllerNames;
}

ASP.NET MVC SEO URL

My goal is to have the url routing as following:
http://www.abc.com/this-is-peter-page
http://www.abc.com/this-is-john-page
What is the simplest way to achieve this without placing controller name an function name in the url above? If page above not found, I should redirect to 404 page.
Addon 1: this-is-peter-page and this-is-john-page is not static content, but is from database.
Similar to KingNestor's implementation, you can also do the followings which will ease your work:
1) Write Your Model
public class MyUser{public String UserName{get; set;}}
2) add route to global asax
routes.MapRoute(
"NameRouting",
"{name}",
new { controller = "PersonalPage", action = "Index", username="name" });
3) Roll your own custom model binder derived from IModelBinder
public class CustomBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var request = controllerContext.HttpContext.Request;
var username = getUserNameFromDashedString(request["username"]);
MyUser user = new MyUser(username);
return user;
}
}
4) in your action:
public ActionResult Index([ModelBinder(typeof(CustomBinder))] MyUser usr)
{
ViewData["Welcome"] = "Viewing " + usr.Username;
return View();
}
I personally wouldn't suggest a route like that but if it meets your needs you need to do something like:
Have the following route in your Global.asax file:
routes.MapRoute(
"NameRouting",
"{name}",
new { controller = "PersonalPage", action = "routeByName" });
Then, in your "PersonalPageController", have the following method:
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult routeByName(string name)
{
switch (name)
{
case "this-is-peter-page": return View("PeterView");
case "this-is-john-page": return View("JohnView");
case Default: return View("NotFound");
}
}
Make sure you have the appropriate views: "PeterView", "JohnView" and "NotFound" in your Views/PersonalPage/.
I don't think this can be done. AFAIK ASP.NET MVC recognizes routing parameters via the character "/".
Your format, on the other hand, goes by "{controller}-is-{id}-{action}" -- so there is no way the controller can be distinguished from the id and the action.
I think using "/" characters doesn't affect or degrade SEO; it only affects human readability and retention of the URL.
Anyway, the following URL is possible: http://www.abc.com/this-is-the-page-of/Peter by adding another route in the Global.asax RegisterRoutes method:
routes.MapRoute(
"AnotherRoute",
"this-is-the-page-of/{id}",
new { controller = "PersonalPage", action = "Details", id = "" }
);
...assuming that PersonalPageController implements a Details ActionResult method that points to the desired page.

Resources