I try to get url from users and provide MapRoute like this:
routes.MapRoute("checkUrl", "tools/{id}", new { controller = "Home", action = "tools" }, new { });
On this case, it's works for this url: "/tools/www.domain.com/"
But how could I manage such a url: "/tools/www.domain.com/view/child/child/?id=4"
Route can't find such a address.
You can use catchall in nexy maproute or use it instead of id.
You can not directly pass the URL as a parameter. You have to pass in a query string.
Before passing the URL you have to encode the URL.
Refer my URL for pass "/tools/www.domain.com/view/child/child/?id=4" in below.
http://localhost:54964/Home/Index?id=www.domain.com%2Fview%2Fchild%2Fchild%2F%3Fid%3D4
I getting value in the id parameter in the method.
public ActionResult Index(string id)
{
return View();
}
Related
I have a route as
routes.MapRoute(
"User", // Route name
"Person/{action}", // URL with parameters
new { controller = "User" } // Parameter defaults
);
that means if I put url like
http://localhost/myApp/Person/Detail
then it should invoke Detail action of User controller, right?
Ok, I have done it and routing also works good, means it invoke action properly.
Now if I want to get controller name then I will use
ControllerContext.RouteData.Values["controller"];
and that will give me User, but I want it to be Person (i.e. as in URL). How can I get that?
The Request.Url property of Controller will return a Uri object containing details of the current url, including the segments.
string[] segments = Request.Url.Segments;
// returns ["/", "Person/", "Detail"]
string value = segments[1].Remove(segments[1].Length - 1);;
// returns "Person"
you can get controller name by following code
HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString();
If you're in a view, then you can do:
ViewContext.RouteData.Values["Controller"]
and for custom url you can define
[Route("myApp/Person/{action?}")]
public ActionResult View(string id)
{
if (!String.IsNullOrEmpty(id))
{
return View("ViewStudent", GetStudent(id));
}
return View("AllStudents", GetStudents());
}
I have a controller function which accepts a strongly typed model as parameter.
When i enter ANY url mapping to the controller but not on a specific action on the post request ,
then the controller executes this function instead of returning a 404 code.
When i Change the function's parameter to a primitive type variable then the problem does not occur. (i have tried using other strongly typed models as parameters and again the problem occurs)
Here's the function.
public class PhoneApiController : ApiController
{
[HttpPost]
public HttpResponseMessage RegisterApp(RegisterAppInfo appInfo)
{
var resp = Request.CreateResponse(HttpStatusCode.OK, new
{
Success = true,
AppId = 1000,
IdAlias = "QAUBC9",
appInfo = appInfo
});
return resp;
}
}
So when i enter for example
localhost:51464/Api/PhoneApi/Sajsdkasjdklajsasd
the function executes normally.!
I am using the default Route config
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
I don't know if this is a bug or i am doing something wrong.
The URI /Api/PhoneApi/Sajsdkasjdklajsasd does match your route template api/{controller}/{id} with {controller} matching PhoneApi and {id} matching Sajsdkasjdklajsasd. I assume you are making a POST to this URI. So, Web API is mapping your request to the action method RegisterApp with [HttpPost] in the controller class PhoneApiController.
As far as the junk stuff in the URI, it gets mapped to {id}. But your parameter is RegisterAppInfo, which is a complex type and that gets bound from request body and not the URI. That's why it works when you have the complex type. The simple types are bound from URI, query string.
If you have the action method as public HttpResponseMessage RegisterApp(string id, Abc appInfo), you will see that this id parameter gets populated with "Sajsdkasjdklajsasd".
For MVC 4.5 this is the only thing that works
There is currently a bug about this.
Below is a work around in order to get the following route types work
api/{controller}/ //Get All
api/{controller}/{Id} //Get for id
api/{controller}/{Id}/{Action}/ //Get all for action for controller with Id
you need to do the following.
Change your routing over to. (Note the default action..)
config.Routes.MapHttpRoute(
name : "DefaultAPi",
routeTemplate : "api/{controller}/{id}/{action}",
defaults: new
{
id = RouteParameter.Optional,
action = "DefaultAction"
}
);
In your controller change the base methods over to
[ActionName("DefaultAction")]
public string Get()
{
}
[ActionName("DefaultAction")]
public string Get(int id)
{
}
[ActionName("SpaceTypes")]
public string GetSpaceTypes(int id)
{
}
Now everything should work as expected..
Thanks to Kip Streithorst full this, for a full explanation
The way routing works in Web API is:
First it matches the URI against route template. At this stage, it's not looking at your controller actions
Then it looks for a matching controller
Then it looks for a method where (a) the action matches (POST in this case) and (b) every simple parameter type is matched with a value from the URI.
If there is a complex parameter type, it tries to read that from the request body.
By default, Web API tries to bind "simple" parameter types (like int) from the URI, and tries to read complex types from the request body.
See here for details: http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-and-action-selection
I have an action method that looks like this:
public ActionResult Index(string message)
{
if (message != null)
{
ViewBag.Message = message;
}
return View();
}
What happens is that the url of a request to this will look like:
www.mysite.com/controller/?message=Hello%20world
But I want it to look just
www.mysite.com/controller/
Is there a way to remove the query string inside the actionmethod?
No, unless you use a POST method, the information has to get passed somehow. An alternative may be to use an in-between class.
// this would work if you went to controller/SetMessage?message=hello%20world
public ActionResult SetMessage(string message)
{
ViewBag.Message = message ?? "";
return RedirectToAction("Index");
}
public ActionResult Index()
{
ViewBag.Message = TempData["message"] != null ? TempData["message"] : "";
return View();
}
Or. if you simply used a POST
//your view:
#using(Html.BeginForm())
{
#Html.TextBox("message")
<input type="submit" value="submit" />
}
[HttpGet]
public ActionResult Index()
{ return View(); }
[HttpPost]
public ActionResult Index(FormCollection form)
{
ViewBag.Message = form["message"];
return View();
}
You can remove the query string by adding some JavaScript in the razor view.
#section scripts{
<script>
if (location.href.includes('?')) {
history.pushState({}, null, location.href.split('?')[0]);
}
</script>
}
If you navigate to page
www.mysite.com/controller/?message=Hello%20world
Then it'll show
www.mysite.com/controller/
in the browser.
Most modern browsers support this (browser support).
Look into routes. They define how a url with parameters will be written.
If you create a new MVC application, and look at the Global.asax.cs file under `RegisterRoutes(). you should see one entry.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "home", action = "index", id = UrlParameter.Optional } // Parameter defaults
);
Look at each part:
"Default" is the name. This just has to be unique for each route you create.
"{controller}/{action}/{id}" is the pattern you want to use. example.org/home/index?id=2 will be written example.org/home/index/2 instead
new { controller = "home", action = "index", id = UrlParameter.Optional } is defining the defaults if nothing is specified.
So, that route make it so if you go to example.org it will assume you mean example.org/home/index{id is optional}.
Working from that, you can start to see how to create your own routes.
Now, addressing your question the short answer is yes you could make the URL look like that, but not really. You would have to define a route with a default message, and it would only look like that if someone didn't specify a message. You have to tell the controller what the message is. I'm sorry, but the best you can do is define a route that gives you
/message/Hello%20World and using string.replace make that look even nicer `'/message/hello_world'
I'm not sure you're really thinking that through. If you remove the query string... then you remove the query string.. ie, your page won't have the query string value to do whatever it needs to do.
There's a bunch of different hacks you could do.. all of them are not ideal. You could use javascript to strip out the query string. You could redirect to a querystring-less page after setting a session variable.. it's all pretty ugly.
Remember that what the user sees in the address bar is on the client. The client controls that. You can fiddle with it via javascript, but doing so is generally a bad idea. Since hiding things from the user can be considered malware-like behavior.
I recommend using a slug. Check out this post: SOF Slug post
In previous applications, I took this approach to remove querystrings from the URL.
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" });
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.