How can I use "For" Keyword in IActionResult name of .net core? - asp.net-core

As google suggest in this page:
https://support.google.com/webmasters/answer/7451184?hl=en
Simple URLs should convey content information
My product name is tools for car,so my url is http://localhost:4413/Product/tools-for-car
Now the problem is in the Controller,when I use this name in controller,Visual Studio report error for the keyword "For" as below:
I wonder if there is a way that I can use this url name?Or I can only change the name.Thank you.

What you probably want is to specify the routes explicitly:
[Route("[controller]")]
public class ProductController : Controller
{
[Route("tools-for-car")]
public IActionResult CarTools() { … }
}
See the Routing to controller actions documentation for more detail.

Related

Where does this "Required" attribute for the Swagger UI coming from for ASP.NET?

I have the following in my ASP.NET Controller:
[Produces("application/json")]
[Consumes("application/json")]
[Route("api/[controller]")]
[ApiController]
public class ConnectionManagersController : ControllerBase
{
[HttpGet("{connectionManagerID:int}")]
[ProducesResponseType(typeof(ConnectionManagerModel), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<ConnectionManagerModel>> GetConnectionManagerAsync(int connectionManagerdID){}
}
However when I run the app and the Swagger UI comes up I get the following screen:
There are TWO connectionManagerID fields on the Swagger UI - the first is an int (which is should be) and the second is a string and is required which I dont know where that is coming from.
I dont know where the *required field is coming from.
The parameter connectionManagerdID is an int - it is not nullable so in effect it is required.
Try this:
public async Task<ActionResult<ConnectionManagerModel>> GetConnectionManagerAsync(int connectionManagerdID = null){}
It should set it to optional.
it is from here, you will probably get 404, if you don't supply id to url.
[HttpGet("{connectionManagerID:int}")]
and if you don't want to be required try this
[HttpGet("{connectionManagerID?:int}")]
in this case maybe it makes sense to change the action too
public async Task<ActionResult<ConnectionManagerModel>> GetConnectionManagerAsync(int? connectionManagerdID){}
or you can keep what you have. It will be 0 by default.
I had the two parameters spelled differently. :(

Blazor #page route url define with variable

I have a question for Blazor Server Side.
I want to #page route url define with variable or property.
I can use now with below default method
#page "/route-url"
<h1>Page Test</h1>
#code {
}
But i want use like as below method
#page MenuItem.Role
<h1>Page Test</h1>
#code {
}
I'm tried above method then throwed exception. Like as below exception.
C:\Projects\TestBlazorProject\Pages\TestPage.razor(1,7): error RZ1016: The 'page' directive expects a string surrounded by double quotes. [C:\Projects\TestBlazorProject\TestBlazorProject.csproj]
How to define #page route url with any different variable or any class property?
Can this be done?
Yes
How?
Page file
#attribute [Route(PageRoute.TaskList)]
<div>PAGE HTML HERE</div>
#code{ ... }
PageRoute.cs:
public static class PageRoute
{
public const string TaskList = "/route-url";
}
Explanation
The page directive gets compiled down to an attribute and has the same restrictions as C# attributes.
You can use the #attribute with the [Route] attribute and use string concatenation instead of string interpolation to define a constant for the route, since that's what the C# compiler supports.
Why would anybody do this?
This is a good coding practice, because you are not hardcoding the page/component name in multiple places, but only in one place.
So one fine day when you manager asks to change page name "Earth" to "Planet3",
you just change it in 1 place, and be 98% sure that your app wont crash because of it.
#page isn't C#, it's Razor talk. Razor files are pre-compiled into c# files during compilation.
As an example, this is the important section of the C# pre-compiled file for Index.razor (Index.razor.g.cs):
[Microsoft.AspNetCore.Components.RouteAttribute("/")]
public partial class Index : Microsoft.AspNetCore.Components.ComponentBase
{
#pragma warning disable 1998
protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder)
{
__builder.AddMarkupContent(0, "<h1>Hello, world!</h1>\r\n\r\nWelcome to your new app.\r\n\r\n");
__builder.OpenComponent<Blazor.Starter.Shared.SurveyPrompt>(1);
__builder.AddAttribute(2, "Title", "How is Blazor working for you?");
__builder.CloseComponent();
}
#pragma warning restore 1998
}
Note that #page has become a compile time attribute [Microsoft.AspNetCore.Components.RouteAttribute("/")]. It's fixed at compiletime, you can't change it at runtime.
Routes are set this way because the router builds a routemap - essentially a dictionary of route url/component class pairs - when the application loads by trawling the application assembly for any component classes with a Route attribute. On a routing event it reads the new url, finds the component class and loads it into the layout. Any variables - stuff in curly brackets - get passed into the component as Parameters.
You haven't made it clear what the line below is supposed to do:
#page MenuItem.Role
Do you want to capture a variable supplied in the route into MenuItem.Role?
Do you want to set this page's route to the value in MenuItem.Role?
If 1, either the other answers will work for you. If 2, you'll need to consider writing your own router. A subject beyond a simple answer here.
I think you can achieve that by following.
#page "/{Role}"
#code{
[Parameter]
public string Role { get; set; }
}
Building off of the above you can I was able to get this to work with the code isolation approach.
Client/Pages/Foo/
----Index.razor
----Index.cs
namespace Client.Pages.Foo;
[Microsoft.AspNetCore.Components.RouteAttribute(Path)]
public partial class Index
{
public const string Path = "/Foo";
}

ASP.NET Core: Generate URL to the base of a controller (NOT TO AN ACTION)

I need to use UrlHelper to generate the URL to the base of a controller. If you must know, the action is Statements, but that is generated by JavaScript provided by a third party that is out of my control. Read: If the name of ANY action, including Statements or Index, is in the generated URL, then my application will fail. Thank you!!!
Stuart Simon
You can do this using a combination of RouteAttribute and Url.RouteUrl.
Controller:
[Route("test", Name = "test-route")]
public class TestController : Controller
{
[HttpGet]
public IActionResult Index()
{
return View();
}
}
This associates the name test-route with /test. Calling Url.RouteUrl("test-route") will return /test.

Using ApiExplorerSettings GroupName in Route in ASPNET Core

In ASP.NET Core - Web API project
Using [ApiExplorerSettings(GroupName = "<group-name>")] decorated on ApiController
and in [Route] attribute I want to refer above GroupName property value.
Also note I do have [ApiVersion("<some-version>")] on same controller to classify further.
Here are some samples to explain:
Example 1:
Attribute on LeadController: [ApiVersion("1.0"), ApiExplorerSettings(GroupName = "sales"), [Route("api/{groupName}/v{version:apiVersion}/leads"]
Expected translated route format: /api/sales/v1/leads
Attribute on AccountsController: [ApiVersion("2.1"), ApiExplorerSettings(GroupName = "finance"), [Route("api/{groupName}/v{version:apiVersion}/accounts"]
Expected translated route format: /api/finance/v2.1/leads
In above {version:apiVersion} gives me ApiVersion value (I assume because that attribute has ToString set to version value). But when I try {groupName} or {grp:groupName} or {grp:ApiExplorerSettings.GroupName} - none of them works. How can access this group name in route attribute?
Do you have any special settings somewhere else, it works fine on my side.
LeadController:
[ApiVersion("1.0"), ApiExplorerSettings(GroupName = "sales"),Route("api/{groupName}/v{version:apiVersion}/leads")]
[ApiController]
public class LeadController : ControllerBase
{
public string Get()
{
return "sales group";
}
}
AccountsController:
[ApiVersion("2.1"), ApiExplorerSettings(GroupName = "finance"), Route("api/{groupName}/v{version:apiVersion}/accounts")]
[ApiController]
public class AccountsController : ControllerBase
{
public string Get()
{
return "finance group";
}
}
Result:
ApiExplorerSettings.GroupName is only for the logical group name used in API descriptions. It is not used or evaluated in route templates. There is no way to make that work. That is why it never expands. It is possible to use a {groupName} route parameter, but it will be just that - a route parameter.
It's not entirely clear if you are trying to control grouping for the API Explorer or use a route parameter. Grouping is typically used by the API Explorer. API Versioning will assign or override the group name so that APIs are bucketized by their version. It is possible to change this behavior, but you'll need an API Explorer (via IApiDescriptionProvider) or OpenAPI/Swagger document generator extension to do it.

Using attribute routing on a controller is forcing me to manage all routes

I am just getting to grips with Asp.net Core and I'm trying to set up a basic site.
I want to build an admin panel that is under a subdirectory.
I have a simple controller which was scaffolded by the EF crud feature.
So it seems that from the examples I should just be able to add a [Route()] attribute to the controller and it will prefix everything. Something like this:
[Route("Admin/Subfolder/[controller]")]
public class EventsController : Controller
{
}
But when I do that I just get an error page saying "multiple actions matched" and it lists index, details, create, etc.
I can get it working if I then go through every method and put a [Route()] attribute on it but this doesn't seem to be in line with the documentation.
It feels like I should be able to just add a prefix to the controller route without having to take over management of every route within the controller. Case in point, the POSTS are not working now and I'm not sure what the format of the route attribute should be for them.
What am I doing wrong?
You are doing it correctly. Default route attribute can be applied at the controller level. “Placing a route attribute on the controller makes all actions in the controller use attribute routing.”
Can you post complete code of your controller? There must be something else going on in there. Make sure you use HttpPost/HttpGet attribute for actions with the same name, like so:
[Route("Admin/Subfolder/[controller]")]
public class EventsController : Controller
{
[HttpGet]
public IActionResult NewEvent()
{ }
[HttpPost]
public IActionResult NewEvent()
{ }
}
Good explanation on routing can be found here