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());
}
Related
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();
}
I have been working on desktop applications mostly and thought to learn web development using ASP.Net MVC5 and thus going through the book by Jon Galloway. So I was reading about how you can pass the parameters to action methods using query string like
/Store/Browse?genre=Disco
or directly embed them in the url like
/Store/Details/5
Now the controller code that I wrote (taken from book) is below :
namespace MvcMusicStore.Controllers
{
public class StoreController : Controller
{
// GET: Store
public string Index()
{
return "Hello from Store.Index()";
}
public string Browse(string genre)
{
string message = HttpUtility.HtmlEncode("Store.Browser, Genre = " + genre);
return message;
}
public string Details(int id)
{
string message = "Store.Details, ID = " + id;
return message;
}
}
}
The url opens fine and the actions return the message as expected. But just to try I tried to pass the genre value by embedding it in the url like
/Store/Browse/Rap
but that doesn't work like it did for the Details() action. I thought it may have to do something with the datatype of genre, so I tried changing the data type of id in Details() to string as below :
public string Details(string id)
{
string message = "Store.Details, ID = " + id;
return message;
}
}
and opened the url
/Store/Details/5
and the Details() action returns message with id value 5, but when i do the same for Browse() action
/Store/Browse/Rap
the action doesn't return the message with genre value "Rap". I tried to pass the genre value and removed the html encoding to see if that had anything to do with it, but it didn't.
I looked at the post here but that didn't help either. Any comments appreciated.
Your using the Default route which is defined as
url: "{controller}/{action}/{id}",
and expects a value for id. When you use /Store/Browse/Rap, then the value of the 3rd segment ("Rap") will be bound to a paramater named id, but your Browse() method does not contain one (its named genre).
Either change the name of the parameter so its
public string Browse(string id)
and the value of id will be "Rap",
Or create a specific route definition and place it before the Default route (and keep the Browse() method as is)
routes.MapRoute(
name: "Browse",
url: "Store/Browse/{genre}",
defaults: new { controller = "Store", action = "Browse", genre = UrlParameter.Optional }
);
... // default route here
Side note: You do not need to change the type of the parameter in the Details method if your always passing a value that is a valid int
I am experiencing an issue with a refactoring of our payment processing action method (called by our 3rd-party online payment provider). We have a product controller with the [Authorize] and [RoutePrefix("products")] attributes at the class level, and action methods including the following:
Product(string contractNumber) with routing attribute [Route("{productCode}")]
MakePayment(string productCode, PaymentAmountType? amountSelection, decimal? amountValue) with routing attribute [Route("{productCode}")] and [HttpPost] attribute
ProcessPayment(string productCode, string result) with routing attribute [Route("{productCode}")]
Because our payment gateway needs to be able to call our ProcessPayment action before the visitor is redirected to that same URL, we've had to refactor that to a separate controller without the [Authorize] attribute. (We already have mechanisms to prevent double-crediting a payment.)
Before this refactoring, the MakePayment action method correctly formulated the correct return URL in the following call to Url.Action():
var rawCallbackUrl = Url.Action("ProcessPayment", new { productCode = productCode });
The ProcessPayment action method has now been moved out of the product controller and into a new controller, ExternalCallbackController, which has no attributes (let alone [Authorize]), in order to avoid having an HTTP 401 response returned to the payment provider.
The route attribute on ProcessPayment is now [Route("order-processing/{productCode}/process-payment")] to avoid clashing with the RoutePrefix on the product controller. All references to this updated action method are updated to specify the ExternalCallbackController.
Manually browsing to the URL causes the breakpoint set inside ProcessPayment to be hit, so the route apparently works successfully.
The problem is that in MakePayment, the following call returns null:
var rawCallbackUrl = Url.Action("ProcessPayment", "ExternalCallback", new { productCode = productCode });
Given that I am specifying both the controller and action method, why is Url.Action(...) not returning the expected URL in the form order-processing/{productCode}/process-payment?
From Day 1, our RegisterRoutes() method in RouteConfig has had attribute routing properly initialised with
routes.MapMvcAttributeRoutes();
How can I get the correct URL returned from the call to Url.Action(...)?
Doh - I've figured out what went wrong. Despite the sanitising of names in the source code (which were specific to our client), it turns out that there was a mismatch in the following call:
var rawCallbackUrl = Url.Action("ProcessPayment", "ExternalCallback", new { productCode = productCode });
and the ProcessPayment() action method.
This is akin to the following (note the use of productNumber instead of productCode):
var rawCallbackUrl = Url.Action("ProcessPayment", "ExternalCallback", new { productNumber = productNumber });
trying to reference the action method:
[Route("order-processing/{productCode}/process-payment")]
public ActionResult ProcessPayment(string productCode, string result)
{
...
}
It also turns out that I can also use the same prefix "products" instead of "order-processing", as MVC creates one Route per attribute route in the routing table. Hope that helps others stuck in a similar situation.
I got this Error : Url.Action return null.
public async Task<IActionResult> ForgotPassword(ForgotPassword forgotPassword)
{
if (ModelState.IsValid)
{
// Find the user by email
var user = await userManager.FindByEmailAsync(forgotPassword.Email);
// If the user is found AND Email is confirmed
if (user != null && await userManager.IsEmailConfirmedAsync(user))
{
// Generate the reset password token
var token = await userManager.GeneratePasswordResetTokenAsync(user);
// Build the password reset link
var passwordResetLink = Url.Action("ResetPassword", "Account",
new { email = forgotPassword.Email, token }, Request.Scheme);
ViewBag.PRL = passwordResetLink;
// Send the user to Forgot Password Confirmation view
return View("ForgotPasswordConfirmation");
}
return View("ForgotPasswordConfirmation");
}
return View(forgotPassword);
}
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
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" });