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
Related
I have the requirement to use Html.RenderAction like you would in ASP.NET MVC.
For instance I have a Home Page with News and Products on.
I would like to do for instance
#Html.RenderAction("/api/products/featured")
Which would start a new service call and output the template to the html stream.
Is this possible using ServiceStack Razor and if so how do I accomplish it?
The PartialExamples.cshtml test page shows different examples of rendering a razor view inside a page, e.g:
Using the new RenderToAction() method which lets you execute a Service and it's rendered partial view with a route and QueryString, e.g:
#Html.RenderAction("/products/1")
This also takes an optional view name if you want a different view than the default:
#Html.RenderAction("/products/1", "CustomProductView")
There's also the normal Html.Partial() to specify which view and model you want to render in the page, e.g:
#Html.Partial("GetProduct",
base.ExecuteService<ProductService>(s => s.Any(new GetProduct { Id = 1 })))
ExecuteService is simply a wrapper around the equivalent ResolveService in a using statement, i.e:
#{
Response response = null;
using (var service = base.ResolveService<ProductService>())
{
response = service.Any(new GetProduct { Id = 1 });
}
}
#Html.Partial("GetProduct", response)
The new RenderToAction() method in Razor Views was added in v4.0.34+ which is now available on MyGet.
*I may be duplicating my answer or I lost it somehow
Looking at the ServiceStack.Razor.ViewPage class there is an Html property of type ServiceStack.Html.HtmlHelper. I don't see 'RenderAction' as a method (or extension method) on this class so it doesn't appear to be available. There is a 'Partial' method that takes the ViewName and an overload that takes a ViewName and an object. Based on your above comment this doesn't appear to be a useful solution.
If I'm correct about the above, I think you'd need your 'Featured View Template' to pull in the data. Could add soemthing like
{ FeaturedResponse products = new JsonServiceClient("http://localhost").Get<FeaturedResponse>("/api/products/featured"); }
to your template. This would allow you to use the products variable like a Model.
Or, use JavaScript to pull the data into the template. You would have have to use JavaScript to get your data into the HTML elements, though.
You could then render the template using #Html.Partial('Featured')
Hope this helps.
I've got an MVC application with basic view:
myapp.com/category
and a switcher to second one:
myapp.com/category/list
App is used as independent one and as also in other application into iframe where src is: myapp.com/category. I want do not show page header when it is used into iframe, how can I achieve it? I was trying to add querystring, myapp.com/category?show=false, and set this as iframe src, but when I switch to the second view the parameter is not passed.
You could create a helper method to construct URLs that would keep the show parameter in place. For example:
public static string GetModifiedUrl(this UrlHelper helper, string url)
{
string qstring = helper.RequestContext.HttpContext.Request.QueryString["show"];
if (!string.IsNullOrEmpty(qstring)) url += "?show=" + qstring;
return url;
}
Then in the views, for example:
<a href='#Url.GetModifiedUrl(Url.Action("Index", "Home"))'>Home</a>
Another option is to create add a value to the session on the first request, and use that instead. Ie, put some logic in the controller like this:
var qs = Request.QueryString["show"];
if (!string.IsNullOrEmpty(qs))
{
Session["show"] = qs;
}
Then in the views, use #Session["show"] instead of #Request.QueryString["show"] to decide whether you show the header.
Break the main view into two partial views.
Then, when calling for the master/external app, call the partial view that has just the content.
When calling the regular native app, call a VIEW that contains both the partial views (header as well as content).
Given the following string:
/MyController/MyAction/4
How do I generate a link within another controller's action to link to the appropriate address?
If I do the following:
#Html.ActionLink("click", Url.Action(item.Link))
// where item.Link is where /MyController/MyAction/4 is stored
I get a link that resembles:
www.localhost.com/CurrentController/CurrentController/MyController/MyAction/4
I need to not have the "CurrentController" part (yes, there are two of them - I think that is because I am doing a #Html.ActionLink and an Url.Action).
How would I get my appropriate link?
If you already have the /MyController/MyAction/4 path you need stored in item.Link, could you just build the <a> tag yourself?
Link Text
Use the RouteUrl() method to achieve what you want. For more information, you can check this page as well.
I think what you are wanting is to link to another controller and action?
You need to do this;
#Html.ActionLink("Click", "ActionName", new {Controller = "ControllerName"})
Then you can add some HtmlAttributes onto that to;
#Html.ActionLink("Click", "ActionName", new {Controller = "ControllerName"}, new { #class= "className" })
Edit
If you are passing this string value in, then why not just use;
Click
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
}
Is it possible to detect a route value in a view?
Such as /pages/create/1 and I want to check to see if 1 is there?
Basically, I want to render a different partial view based on this value though I'm fairly sure this is probably not the best way to go about what I'm trying to achieve.
On a side note, instead of doing the above is it possible for me to be able to change what partial views are rendered in a view based on a value from within my controller?
ViewContext.RouteData.Values["whatever"]
You can inspect a RouteData object through ViewPage.ViewContext.RouteData. Then check for values using something like
string areaname = routeData.Values["area"] as string;
string controllername = routeData.Values["controller"] as string;
string actionname = routeData.Values["action"] as string;
string id = routeData.Values["id"] as string;
If you find that you want to inspect these values in the controller instead, you can access them using ControllerBase.ControllerContext.RouteData. Something similar applies for action filters etc.
Other answers are correct, but thought i'd address your last sentence:
On a side note, instead of doing the above is it possible for me to be able to change what partial views are rendered in a view based on a value from within my controller?
Well partial view's are rendered in the View itself (unless calling from JavaScript and binding directly to DOM) with the following code:
<%: Html.RenderPartial("SomePartial") %>
So to prevent "code soup" (if statements) in your view, you use a HTML helper which calls through to RenderPartial after inspecting the ViewContext:
public static string RenderCustomPartial(this HtmlHelper helper, RouteData rd)
{
string partialName;
if (rd.Values["SomeParam"] == 1)
partialName = "PartialOneName";
else
partialName = "PartialTwoName";
return helper.RenderPartial(partialName);
}
And then in the View:
<%: Html.RenderCustomPartial(ViewContext.RouteData) %>
You could make some mods to the above - like access the route data directly in the extension, pass through the model to bind in the partial, etc - but you get the idea.
Alternatively you could do the above IF statement in your controller, and stuff the partial view name in the ViewData, then use that in the regular RenderPartial call in your View.
Whatever floats your boat. :)