Creating an action link in a Controller - asp.net-mvc

In one of my controller actions, I'm generating some XML. One of the attributes in that XML is an href to another controller and action, with some parameters. The XML should look something like this:
<projects>
<project id="42" name="Project X", href="/projects/42"/>
<!-- etc. -->
</projects>
I don't mind if the URL is relative or absolute, but my question is this: how do I generate the URL in the controller code, in a type-safe way?
In other words, how do I do what HtmlHelper.ActionLink does, but from a controller?

Found it by using Reflector:
string href = Url.Action("DetailsAsXml", new { projectId = item.Id });

Related

Pass relative URL ASP.NET MVC3

I'm trying to pass a list of URL's with Id attributes from a controller to a view.
I can pass a <a href=...> link back but I don't think writing a 'localhost' absolute path is a clean way of approaching this. I cant pass an ActionLink back as it returns the full string. Is ther a simple solution to this problem? Thanks in advance.
Using this overload of the UrlHelper.Action() method and Request object you can get a complete URL including the route parameters such as IDs and the actual hostname of the application.
string url = Url.Action("action", "controller",
new System.Web.Routing.RouteValueDictionary(new { id = id }),
"http", Request.Url.Host);
UrlHelper is available in the controller via its Url property.
You can then pass such URL into your view.
It is also possible to use UrlHelper directly inside your view to create URLs for controller actions. Depends if you really need to create them inside the controller.
Edit in response to comments:
Wherever you need to place the URLs, this "URL builder" you are looking for is still the UrlHelper. You just need to pass it (or the generated URLs) where you need it, being it inside the controller, view or custom helper.
To get the links inside the unsorted list HTML structure you mention, you need to put anchors inside the list items like this:
<ul>
<li>Link</li>
...
</ul>
Then again you just need to get the URLs from somewhere and that would be from UrlHelper.
Simple and easy.
text
the route id = the parameter that is going to be inserted into your method.
eg.
function Details(int id) {
//id has the value of my_var_id
}

How to create canocical from controller in grails?

In grails, I have a link like /myapp/questions/all
The all is a parameter (all, replied, ...) passed to my controller.
I have a form to search question depending of type : in all, in replied, ...
In the search form, I have an hidden field to pass parameter.
But the url displayed is /myapp/questions/ ans not /myapp/questions/all
So I tried with url : url="[action:'question', controller:'mycontroller', params:['monparam':'${mavariable}']]"
but it's not working.
Any idea ?
Thanks
You can do it like this:
class UrlMappings {
static mappings = {
name nameOfTheMapping: "/question/$para/" {
controller = "mycontroller"
action = "question"
}
...
Then you can access the mapping by:
<a href='${createLink(mapping: 'nameOfTheMapping', params: [para: para.encodeAsUrl()])}' title='test'>Test</a>
The above code is created in my taglib, so it maybe a little different if you want to use it in a view.
I don't completely understand your question, but it seems you are not following the grails convention. the url is of the form
/app/controller/action
so grails is interpreting the 'all' part of your url as the action to invoke on the questions controller (what I got from your 'link like /myapp/questions/all').
Where I got confused was with your url specification.
url="[action:'question', controller:'mycontroller', params:['monparam':'${mavariable}']]"
Based on that, you should have a controller called 'mycontroller', with an action called 'question' on it. The url you will see in the browser would be
/app/mycontroller/question?monparam:whatever
See here for details on controllers in general.
You need to edit grails-app/conf/UrlMappings.groovy and create a mapping to the controller that omits the action. (since you're handling this all within one action)
something like
"/questions/$question_type" (controller: 'questions', action: 'your_action')
where "your_action" is the name of the action that is processing these requests.
Then in QuestionsController.groovy:
def your_action = {
// use question_type as needed
def questions = Questions.findByQuestionType(params.question_type)
// etc.
}
You can do a variety of things to affect the mapping of urls to requests, check out the UrlMapping section in the Grails User Guide.

path to controller action

It is no problem to use Html.ActionLink in a View to obtain the right path to a controller action. I am just wondering whether this is also possible in other layers (e.g. controller). I am asking this because I am generating an <ul> recursively with some data access to render a 'link tree structure'. Thanks!
Christian
In the controller you can use UrlHelper to create url.
string html = string.Empty;
UrlHelper url = new UrlHelper(HttpContext.Request.RequestContext);
string edit = url.Action(Constants.action_Edit, Constants.ctrl_myController, new { someId });
html += "Edit ";
This would create a string with html link inside. In the example I use constants to give correct action and controller, but it could of course be a "normal" string.
Let me know if you need more scenarios

ASP.NET MVC create absolute url from c# code

How do i generate an absolute url from the c# code?
I want to generate a url like this: localhost/{controller}/{action}/{id}. Is there a way to do it in c# like how it can be done in the views?
It wont be generated inside the controller but inside a ViewModel.
string absUrl = Url.Action("Index", "Products", null, Request.Url.Scheme);
Just add Request.Url.Scheme. What this does is add a protocol to the url which forces it to generate an absolute URL.
Check out a similar question Using html actionlink and URL action from inside controller. Seems to be similar and reusable for your requirements.
If you don't want to "build" the url and just want the full path of the current page, this will do the trick
Context.Server.UrlEncode(Context.Request.Url.AbsoluteUri)
I know it's not as elegant as an Extension Method but thought of sharing it for educational purposes
As of latest update to MVC you can use below overload for Url.Action
string url=Url.Action("ActionName", "Controller",
new RouteValueDictionary(new { id= someid }),
//url param
HttpContext.Request.Url.Scheme,
HttpContext.Request.Url.Host);
which generates
http://localhost:port/Controller/ActionName?id=someid

How to route legacy type urls in ASP.NET MVC

Due to factors outside my control, I need to handle urls like this:
http://www.bob.com/dosomething.asp?val=42
I would like to route them to a specific controller/action with the val already parsed and bound (i.e. an argument to the action).
Ideally my action would look like this:
ActionResult BackwardCompatibleAction(int val)
I found this question: ASP.Net MVC routing legacy URLs passing querystring Ids to controller actions but the redirects are not acceptable.
I have tried routes that parse the query string portion but any route with a question mark is invalid.
I have been able to route the request with this:
routes.MapRoute(
"dosomething.asp Backward compatibility",
"{dosomething}.asp",
new { controller = "MyController", action = "BackwardCompatibleAction"}
);
However, from there the only way to get to the value of val=? is via Request.QueryString. While I could parse the query string inside the controller it would make testing the action more difficult and I would prefer not to have that dependency.
I feel like there is something I can do with the routing, but I don't know what it is. Any help would be very appreciated.
The parameter val within your BackwardCompatibleAction method should be automatically populated with the query string value. Routes are not meant to deal with query strings. The solution you listed in your question looks right to me. Have you tried it to see what happens?
This would also work for your route. Since you are specifying both the controller and the action, you don't need the curly brace parameter.
routes.MapRoute(
"dosomething.asp Backward compatibility",
"dosomething.asp",
new { controller = "MyController", action = "BackwardCompatibleAction"}
);
If you need to parametrize the action name, then something like this should work:
routes.MapRoute(
"dosomething.asp Backward compatibility",
"{action}.asp",
new { controller = "MyController" }
);
That would give you a more generic route that could match multiple different .asp page urls into Action methods.
http://www.bob.com/dosomething.asp?val=42
would route to MyController.dosomething(int val)
and http://www.bob.com/dosomethingelse.asp?val=42
would route to MyController.dosomethingelse(int val)

Resources