what is the usage of name Property in HttpGet ( such as [HttpGet("/products2/{id}", Name = "Products_List")]) - asp.net-core

In asp.net core, I seen
[HttpGet("/products2/{id}", ***Name = "Products_List")]***
public IActionResult GetProduct(int id)
{
return ControllerContext.MyDisplayRouteInfo(id);
}
what is the usage of name Property in HttpGet (such as[HttpGet("/products2/{id}", Name = "Products_List")])
And, How Can I read/send a Multipart/form-data from/to an apiapicontroller/client?

Yes, it can be used like this. The second parameter of Url.Link is an object.
#Url.Link("Products_List", new { id = 1 })
Also this property RouteUrl can use it.
#Url.RouteUrl("Products_List",new { id=2})
About route name, this is the official introduction:
The route names give the route a logical name. The named route can be used for URL generation. Using a named route simplifies URL creation when the ordering of routes could make URL generation complicated. Route names must be unique application wide.
Route names:
Have no impact on URL matching or handling of requests.
Are used only for URL generation.
If you send a Multipart/form-data. The apicontroller can get it with FromForm.
[HttpGet("routepath")]
public IActionResult get([FromForm]SampleModel model)
{
//...
}

I found that can be used to string uri = Url.Link(“ Products_List”, id = 1);
Is there Some one can give me more detailed information?

Related

How to return a status code from an endpoint that can then be handled by app.UseStatusCodePages() middleware?

If I return StatusCode(403) or any other error code from an endpoint, any configuration of app.UseStatusCodePages<whatever> will be ignored.
I believe this is because the StatusCode(<whatever>) will automatically create a result object, and UseStatusCodePages only kicks in if there is an error status code and no content.
So how do I set a status code result in an IActionResult type endpoint and then return without setting any content so that UseStatusCodePages will handle the job of providing a suitable resonse?
As far as I know, the UseStatusCodePages will just be fired when the action result is the StatusCodeResult.
If you put some value inside the status codes, it will return the object result which will not trigger the UseStatusCodePages.
So I suggest you could directly use StatusCodeResult(403), then if you want to put some value to the StatusCodeResult, I suggest you could put it inside the httpcontext's item.
More details, you could refer to below codes:
public IActionResult OnGet()
{
HttpContext.Items.Add("test","1");
return StatusCode(403);
}
Program.cs:
app.UseStatusCodePages(async statusCodeContext =>
{
var status = statusCodeContext.HttpContext.Items["test"];
// using static System.Net.Mime.MediaTypeNames;
statusCodeContext.HttpContext.Response.ContentType = Text.Plain;
await statusCodeContext.HttpContext.Response.WriteAsync(
$"Status Code Page: {statusCodeContext.HttpContext.Response.StatusCode}");
});
Result:
The issue was that I have the ApiController attribute on the endpoint controller. One of the things this attribute does is to automatically create a ProblemDetails response body for any failed requests, and it is this that prevents UseStatusCodePages from having any effect.
The solution is to either remove the ApiController attribute if you do not require any of its features, or alternatively its behaviour of automatically creating ProblemDetails responses can be disabled using the following configuration in Program.cs (or Startup.cs in old style projects).
builder.Services.AddControllers().ConfigureApiBehaviorOptions(options =>
{
options.SuppressMapClientErrors = true;
});

In ASP.NET Core, is it possible to generate a URI in the controller for a Get action that takes two parameters? If so how?

I have an association controller called ConnectionManagerCategoriesController. It has two Get methods on it. One to get all Categories for a ConnectionManager and one to only retrieve one Categoy for the ConnectionManager based upon the name. I have a Post to create a new category and I am trying to generate a uri for LinkGenerator. However when the URI that is created, it uses the GetConnectionManagerCategories method instead of the GetConnectionManagerCategory. I dont know why or how to do it differently.:
[Route("api/connectionmanagers/{connectionManagerID:int}/categories")]
[ApiController]
public class ConnectionManagerCategoriesController : ControllerBase
{
private readonly LinkGenerator _linkGenerator;
[HttpGet]
public async Task<ActionResult<IEnumerable<ConnectionManagerModel>>> GetConnectionManagerCategoriesAsync(int connectionManagerID){}
[HttpGet("{categoryName}", Name = "GetConnectionManagerCategoryAsync")]
public async Task<ActionResult<ConnectionCategoryModel>> GetConnectionManagerCategoryAsync(int connectionManagerID, string categoryName){}
[HttpPost]
public async Task<ActionResult<ConnectionCategoryModel>> AddConnectionCategoryAsync(int connectionManagerID, string categoryName, [FromHeader(Name = "x-requestid")] string requestId)
{
var url = _linkGenerator.GetUriByRouteValues(HttpContext,
"GetConnectionManagerCategoryAsync",
values: new { connectionManagerID, categoryName = commandResult.CategoryName });
return Created(url, commandResult);
}
It returns the following uri to Swagger: 'http://localhost:6704/api/connectionmanagers/1/categories?categoryName=Almost'
However, when I log the uri in the code it is: http://localhost:6704/api/connectionmanagers/1/categories/newvalueadded
Is this even possible?
You have to show how are trying to run the action, in order to get some explanations. Routing is very tricky and it is better not to try to create routes the way you are creating.
IMHO , it is always a good idea to define the whole route, not just the part. Especially if you use Swager
[HttpGet("{~/api/connectionmanagers/{connectionManagerID:int}/categories/{categoryName}")]
public async Task<ActionResult<ConnectionCategoryModel>> GetConnectionManagerCategoryAsync(int connectionManagerID, string categoryName){}

Route to allow a parameter from both query string and default {id} template

I have an action in my ASP.Net Core WebAPI Controller which takes one parameter. I'm trying to configure it to be able to call it in following forms:
api/{controller}/{action}/{id}
api/{controller}/{action}?id={id}
I can't seem to get the routing right, as I can only make one form to be recognized. The (simplified) action signature looks like this: public ActionResult<string> Get(Guid id). These are the routes I've tried:
[HttpGet("Get")] -- mapped to api/MyController/Get?id=...
[HttpGet("Get/{id}")] -- mapped to api/MyController/Get/...
both of them -- mapped to api/MyController/Get/...
How can I configure my action to be called using both URL forms?
if you want to use route templates
you can provide one in Startup.cs Configure Method Like This:
app.UseMvc(o =>
{
o.MapRoute("main", "{controller}/{action}/{id?}");
});
now you can use both of request addresses.
If you want to use the attribute routing you can use the same way:
[HttpGet("Get/{id?}")]
public async ValueTask<IActionResult> Get(
Guid id)
{
return Ok(id);
}
Make the parameter optional
[Route("api/MyController")]
public class MyController: Controller {
//GET api/MyController/Get
//GET api/MyController/Get/{285A477F-22A7-4691-AA51-08247FB93F7E}
//GET api/MyController/Get?id={285A477F-22A7-4691-AA51-08247FB93F7E}
[HttpGet("Get/{id:guid?}"
public ActionResult<string> Get(Guid? id) {
if(id == null)
return BadRequest();
//...
}
}
This however means that you would need to do some validation of the parameter in the action to account for the fact that it can be passed in as null because of the action being able to accept api/MyController/Get on its own.
Reference Routing to controller actions in ASP.NET Core

How to get current url in view in asp.net core 1.0

In previous versions of asp.net, we could use
#Request.Url.AbsoluteUri
But it seems it's changed. How can we do that in asp.net core 1.0?
You have to get the host and path separately.
#Context.Request.Host
#Context.Request.Path
You need scheme, host, path and queryString
#string.Format("{0}://{1}{2}{3}", Context.Request.Scheme, Context.Request.Host, Context.Request.Path, Context.Request.QueryString)
or using new C#6 feature "String interpolation"
#($"{Context.Request.Scheme}://{Context.Request.Host}{Context.Request.Path}{Context.Request.QueryString}")
You can use the extension method of Request:
Request.GetDisplayUrl()
This was apparently always possible in .net core 1.0 with Microsoft.AspNetCore.Http.Extensions, which adds extension to HttpRequest to get full URL; GetEncodedUrl.
e.g. from razor view:
#using Microsoft.AspNetCore.Http.Extensions
...
Link to myself
Since 2.0, also have relative path and query GetEncodedPathAndQuery.
Use the AbsoluteUri property of the Uri, with .Net core you have to build the Uri from request like this,
var location = new Uri($"{Request.Scheme}://{Request.Host}{Request.Path}{Request.QueryString}");
var url = location.AbsoluteUri;
e.g. if the request url is 'http://www.contoso.com/catalog/shownew.htm?date=today' this will return the same url.
You can consider to use this extension method (from Microsoft.AspNetCore.Http.Extensions namespace:
#Context.Request.GetDisplayUrl()
For some my projects i prefer more flexible solution. There are two extensions methods.
1) First method creates Uri object from incoming request data (with some variants through optional parameters).
2) Second method receives Uri object and returns string in following format (with no trailing slash): Scheme_Host_Port
public static Uri GetUri(this HttpRequest request, bool addPath = true, bool addQuery = true)
{
var uriBuilder = new UriBuilder
{
Scheme = request.Scheme,
Host = request.Host.Host,
Port = request.Host.Port.GetValueOrDefault(80),
Path = addPath ? request.Path.ToString() : default(string),
Query = addQuery ? request.QueryString.ToString() : default(string)
};
return uriBuilder.Uri;
}
public static string HostWithNoSlash(this Uri uri)
{
return uri.GetComponents(UriComponents.SchemeAndServer, UriFormat.UriEscaped);
}
Usage:
//before >> https://localhost:44304/information/about?param1=a&param2=b
Request.GetUri(addQuery: false);
//after >> https://localhost:44304/information/about
//before >> https://localhost:44304/information/about?param1=a&param2=b
new Uri("https://localhost:44304/information/about?param1=a&param2=b").GetHostWithNoSlash();
//after >> https://localhost:44304
There is a clean way to get the current URL from a Razor page or PageModel class. That is:
Url.PageLink()
Please note that I meant, the "ASP.NET Core Razor Pages", not the MVC.
I use this method when I want to print the canonical URL meta tag in the ASP.NET Core razor pages. But there is a catch. It will give you the URL which is supposed to be the right URL for that page. Let me explain.
Say, you have defined a route named "id" for your page and therefore, your URL should look like
http://example.com/product?id=34
The Url.PageLink() will give you exactly that URL as shown above.
Now, if the user adds anything extra on that URL, say,
http://example.com/product?id=34&somethingElse
Then, you will not get that "somethingElse" from this method. And that is why it is exactly good for printing canonical URL meta tag in the HTML page.
The accepted answer helped me, as did the comment for it from #padigan but if you want to include the query-string parameters as was the case for me then try this:
#Context.Request.PathBase#Context.Request.GetEncodedPathAndQuery()
And you will need to add #using Microsoft.AspNetCore.Http.Extensions in the view in order for the GetEncodedPathAndQuery() method to be available.
public string BuildAbsolute(PathString path, QueryString query = default(QueryString), FragmentString fragment = default(FragmentString))
{
var rq = httpContext.Request;
return Microsoft.AspNetCore.Http.Extensions.UriHelper.BuildAbsolute(rq.Scheme, rq.Host, rq.PathBase, path, query, fragment);
}
If you're looking to also get the port number out of the request you'll need to access it through the Request.Host property for AspNet Core.
The Request.Host property is not simply a string but, instead, an object that holds both the host domain and the port number. If the port number is specifically written out in the URL (i.e. "https://example.com:8080/path/to/resource"), then calling Request.Host will give you the host domain and the port number like so: "example.com:8080".
If you only want the value for the host domain or only want the value for the port number then you can access those properties individually (i.e. Request.Host.Host or Request.Host.Port).
var returnUrl = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}{Context.Request.QueryString}";
You may want to get the URL to use it on the razor side, there is an alternative way to get the home app URL:
Url.Content("~/.....")
Example
In the following example, I wanted to generate a QR code and display it in an img tag src, because of using custom route annotation in the Action, I can't use #URL.Action so as an alternative solution I use ~ like this:
<script>
$("#imgCode").attr("src", "#(Url.Content("~/generateQr/"))"+ code);
</script>
Controller Side
[Route("/generateQr/{code}")]
...
ILSpy show how it was done in Microsoft.Owin.dll.
// Microsoft.Owin.OwinRequest
using System;
/// <summary>
/// Gets the uniform resource identifier (URI) associated with the request.
/// </summary>
/// <returns>The uniform resource identifier (URI) associated with the request.</returns>
public virtual Uri Uri => new Uri(string.Concat(Scheme, Uri.SchemeDelimiter, Host, PathBase, Path, QueryString));
I wonder why they removed this property.

How to turn relative route into a relative url?

I have a JSON API action filter that intercepts the output an inserts hypermedia URLs.
I am injecting Microsoft.AspNet.Mvc.ApiExplorer.IApiDescriptionGroupCollectionProvider to give me access to all of the routes.
For a known action, I have the route relative path from Microsoft.AspNet.Mvc.ApiExplorer.ApiDescription.RelativePath. For example:
/articles/{id}
I also have the parameters for the route, in this case it's simply {id}.
I need to turn that relative route into a real Url. For example, for an id of 2, I would expect:
/articles/2
Is there functionality in ASP.NET 5/Core/MVC 6 that will allow me to take the parameter and the route template and create a real Url?
Edit
Thanks for the comments, here's the results of some testing. #dealdiane is correct that Hyprlinkr is not compatible with DNX/aspnet core. I investigated TypedRouting but the helpers do not use the Route templates.
I tried Microsoft.AspNetCore.Mvc.Routing.UrlHelper to create a link. You can inject IUrlHelper like any other service and use the extension methods such as:
UrlHelper helper; // Constructor injected
ApiDescription action; // I have this as a starting point
var actionDescriptor = (ControllerActionDescriptor)action.ActionDescriptor;
var actionName = actionDescriptor.Name;
var controllerName = actionDescriptor.ControllerName;
object values = new {id};
var url = helper.Action(actionName, controllerName, values);
Unfortunately, url is set to:
/articles?id=2
Which is not correct.