All my dynamically generated action links etc. are creating links like /Account/Setup. It looks strange.
I'd like all my links to be lowercase (meaning /account/setup). Any way to do this?
There is simpler solution in .NET Framework 4.5, a new property RouteCollection.LowercaseUrls, here's an example
Take a look at http://goneale.com/2008/12/19/lowercase-route-urls-in-aspnet-mvc/. You can find more information in another stackoverflow at How can I have lowercase routes in ASP.NET MVC?.
The other posts thus far have not tackled the scenario where you navigate to the root of your web directory. If you have a mapping that directs to the HomeController Index action, you would like the following URL to appear:
mysite/home/ or even mysite/home/index
No amount of Html helper function usage will change the fact that, by default, the following will be shown in the browser location bar:
mysite/Home or mysite/Home/Index
Write an extension method for Html:
public static class MyHtmlExtensions
{
public static string LowerActionLink(this HtmlHelper htmlHelper,someargs)
{
return String.ToLowerInvariant(htmlHelper.ActionLink(someArgs));
}
}
Then use Html.LowerActionLink instead of Html.ActionLink
Related
Question:
Edit: It seems my question is actually not a routing issue but an anchoring issue.
If I have assigned a route:
[Route("~/Envelope/List/AcademicYear/{year}")]
public IActionResult AcademicYear(string year)
{
}
How would I correctly use an asp-action to call this route?
using
<a asp-action="List/AcademicYear/" asp-route-id="#Model.AcademicYear">#Model.AcademicYear</a>
returns a url with a %2f (Envelopes/List%2fAcademicYear/2122) instead of / (Envelopes/List/AcademicYear/2122) and thus results in a 404 error
How do I use Custom URL with asp-action to call a specific Action in my Controller?
or
How do I change the routing so I can call an action from a controller with a non default route mapping?
Context:
I've read https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-5.0
and yet i'm still confused on the whole concept of routing and how to interacts with controllers and actions.
In my application I have a controller called Envelope - it controls everything to do with my Envelopes.
I have a class in the Envelopes controller called
public class EnvelopeController : Controller {
public IActionResult List() {... return View()}
and it returns the List.cshtml view. The current url as set by default route mapping: /Envelope/List
In the List.cshtml I have a link that is intended to filter the List on a year parameter
<a asp-action="AcademicYear" asp-route-academicYear="#Model.AcademicYear"> #Model.AcademicYear</a>
My intention is to pass this into a method in the Envelopes controller called "AcademicYear" that gathers the Envelope data stored in temp data, deseralises it and then returns a filtered version based on the parameter:
public IActionResult AcademicYear(string academicYear) { return View("List", newViewModel)}
The return url after this point is correctly: /Envelope/AcademicYear?academicYear=21%2F22
However I would Like to know how to change this so even though I call the Action
<a asp-action="AcademicYear" asp-route-academicYear="#Model.AcademicYear"/>
the URL returned would look like this /Envelope/List/AcademicYear/2122/
Is there a way of doing this? Am I looking at the problem the wrong way? I have thought about simply passing a parameter in the List action and running some form of control to do either set of operations depending on the parameters existence but realistically the List method and the filtering AcademicYear method aren't really doing the same thing and I'd like to seperate out the code into different methods if possible.
Even if its not the appropriate solution I would still like to know if it is possible to change the URL routing for an action after it has been called.
Edit :
I have tried using HttpGet(List/AcademicYear/{academicYear:[a-zA-Z]} however when I do this I can't actually call List/AcademicYear as an asp-action due to the "/" and how that encodes to %2f
Answer:
With the help of the below solutions I realised I was looking at the problem wrong and was actually having issues creating correct anchors.
Reading: https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-5.0#url-generation-and-ambient-values-1
I realised the answer was staring me in the face and I used this alongside the Routes provided for in the answers
<a id="#academicYear.Name" href="#Url.Action("AcademicYear", "Envelope",new {year= academicYear.Name})">
Maybe you just need to decorate your action like that:
[HttpGet("List/AcademicYear/{year:int}")] // or HttpPost it depends on you
public IActionResult AcademicYear(string year) { }
You can add several attribute routes to the action.
[Route("~/Envelope/List/AcademicYear/{year}", Name="ListRoute")]
[Route("~/Envelope/AcademicYear/{year}")]
public IActionResult AcademicYear(string year) { }
and if you need this url
http://localhost:xxxx/Envelope/List/AcademicYear/2021
you can use this html helper, that will create a right anchor tag for you using an attribute route name.
#Html.RouteLink(#Model.AcademicYear, "ListRoute", new { year = #Model.AcademicYear })
I added Name="ListRoute" to the attribute routing (see above)
I'm developing a large ASP.NET Core 2 web application but I still get confused with URLs.
When fist learning, I thought URL's took on the name of the View, but discovered they come from the Controller method.
Here is an example to convey my issue:
I have a controller method named Daysheet, which returns a view and model with the same name.
In the Daysheet view, I call various controller methods from Javascript to perform specific actions. One of them is called AssignStaff which takes two integer parameters.
In the AssignStaff method I again return the Daysheet view with model, but now my URL is "AssignStaff"!
I can't just do a redirect because the whole Daysheet model is not being passed to the AssignStaff method.
I have many situations like this where after calling an action, I end up with another URL that I don't want.
UPDATE/EDIT
Thanks for assistance and apologies if my explanation is confusing. I simply have a view called Daysheet that uses a model. I want to call various controller methods to perform various actions, but I want to stay on the "Daysheet" view/URL.
As mentioned, I can't just redirect because in the action method I no longer have the whole model from the Daysheet view. Also, if I redirect I can't pass the whole model because that causes an error saying the header is too long. I think my only choice may be to use ajax for the actions so that the URL doesn't change.
When you just do Return View("") name in a Controller Action, the URL will be the name of the Action you are using.
If you want to redirect to some specific Action, that will help to make sure the Url matches to where you are. You might want to read more about it here.
To do so, use:
RedirectToAction()
The URLs your application responds to are called "routes", and they are either created by convention or explicitly. The default is by convention, of course, which is a URL in the form of /{controller=Home}/{action=Index}. Index is the default action if that portion of the route is left off, so a request to /foo will by convention map to FooController.Index. HomeController is the default controller, so an empty path (e.g. http://sample.com) will by convention invoke HomeController.Index.
Razor Pages have their own conventions. These do somewhat follow the file system, but exclude the Pages part of the path. So a Razor Page like Pages/Foo/MyRazorPage.cshtml, will load up under /Foo/MyRazorPage.
There there is the Route attribute, which allows you to specify a totally custom route. This attribute can be applied to a controller class and individual actions in the class. For example:
[Route("foo")]
public class MyAwesomeController
{
[Route("bar")]
public IActionResult MyAwesomeAction()
{
return View();
}
}
With that, a request to /foo/bar will actually invoke MyAwesomeController.MyAwesomeAction.
Is there a built-in Sitefinity method for displaying blog post content without the HTML? NOT the standard standalone C# methodology, but a built-in method in Sitefinity so I can avoid duplicating functionality.
A built in method in Sitefinity, not a generic C# solution.
I'd like to show a summary from my content rather than the separate summary field. I'm in my custom blog list .cshtml file, doing this to retrieve content:
Html.Raw(item.Fields.Content).ToString()
Which gives me the content, but I need to display with without the HTML tags a user may have added.
If you refer using Telerik.Sitefinity.Utilities you will get an extension method StripHtmlTags for the string type.
This is a public extension method and you should not have problems using it.
I see there are a few classes in Sitefinity that do HTML stripping:
public static HtmlStripper in Telerik.Sitefinity.Modules.Newsletters.Composition namespace.
and
internal static class HtmlStripper in Telerik.Sitefinity.Utilities.HtmlParsing namespace, which seems to be the one you need, because it has a StripHtml method, but you cannot use it as it is internal.
I agree with #Zohar that in this particular case you should just use a standard C# approach - you cannot go wrong with it.
This is what the implementation would look like
public class Product
{
public integer id {get;set;}
[MultiLangual]
public string name {get;set;}
}
In the database, name would contain something like:
{en:Pataoto, nl: Aardappel, de: Patat, fr: pommes de terre}
This would contain all the translated fields, that a client has given to his own product.
(in this case: a patato).
In the frontend, this would appear as multiple html elements, which i (somehow) detect which language it is, on submitting the form.
My question is, how would i do this? I'm always stuck on creating the attribute and don't know where to continue...
In my attribute, i shouldn't do a lot, just something like this (i think):
public class MultiLangualAttribute : Attribute
{
public MultiLangualAttribute() : base()
{
}
public override string ToString()
{
return base.ToString();
}
}
But how would i detect everything in my views and create a custom layout for it (this should work with and .
It would only contain text.
Any ideas or a better implementation of above, would be VERY usefull :)
I think the better (arguably) implementation is standard way of application localization.
You define your resources and strings under App_GlobalResources folder you will have to create.
For example you will create file Fruits.resx with all your fruits you want to translate in your system language.
Afterwards you will create Fruits.de.resx, Fruits.es.resx etc, with all the languages you want to have in your website.
It is also possible to update the resources at runtime.
Its too much to describe all the approach in this answer, I would rather provide a link or two with detailed tutorial on MVC application localization:
This is classic ASP.NET MVC localization explanation:
Globalization And Localization With Razor Web Pages
Another explanation of the same thing, little more detailed is here:
ASP.NET MVC Localization: Generate resource files and localized views using custom templates
This should be enough for you to localize your app the standard way.
This is a little more advanced approach, when they use language as part of the URL you accessing.
es.yourdomain.com will be in Spanish, fr.yourdomain.com will be in French:
Localization in ASP.NET MVC – 3 Days Investigation, 1 Day Job
With regards to your approach (storing different languages in the database) here's link to microsoft approach for this. Its much more involved and complex, and I am not sure if benefitting you by its complexity, since you end up using database to fetch every single string in your app. Not the most efficient, but possible approach as well:
Extending the ASP.NET Resource-Provider Model
Hope this all will be of helps to you & good luck
I want a strongly typed url class that i will reference whenever I need a url for any links, redirecting, etc.
I don't like:
RedirectToActoin("Action", "Controller");
A site with 50+ views means any naming change is going to break allot of things.
I also want a user frienly api so I can do:
MyUrls.ControllnerName.ActionName
How can I achieve this? is it possible?
Have a look at the T4MVC project (part of MvcContrib). It gives you strongly typed helpers for actions, controllers and views.
Excerpt from the project documentation:
T4MVC is a T4 template for ASP.NET MVC apps that creates strongly typed helpers that eliminate the use of literal strings when referring the controllers, actions and views. It helps make your MVC code much more maintainable, and gives you intellisense where you normally would not have any.
Instead of this:
<% Html.RenderPartial("DinnerForm"); %>
You can write this:
<% Html.RenderPartial(MVC.Dinners.Views.DinnerForm); %>
I actually prefer an approach inspired by the MVCContrib folks, which is to utilize a custom method on the controller that uses a Lambda Expression to specify where you are wanting to go.
protected internal RedirectToRouteResult RedirectToAction<TController>(Expression<Func<TController, object>> action) where TController: Controller
{
var controllerName = typeof(TController).Name.Replace("Controller", string.Empty);
var actionName = ((MethodCallExpression)action.Body).Method.Name;
return RedirectToAction(actionName, controllerName);
}
And using it would look like this:
return RedirectToAction<HomeController>(h => h.Index());
With this approach you get the advantages of having easy to read statements and when you refactor your action names these statements get updated as well (or cause build errors if you don't use the rename refactor).