Controller is after rename of solution not avaible - asp.net-core

I have rename my main solution. My controllers are in another solution. The main solution has a dependencie on the rest-solution. All solution worked very well, but one is not avaible under the old route. I do not change the route of the controller.
Old route before renaming was [Route("api/identity/user")]. If i used it, i get only the errorpage.
Here's what I found out:
If i changed it to another route like [Route("api/identity/asdf")] or [Route("api/identity/user_old")] the controller worked very well.
Clean Solution and Restart Visual Studio don't help
Change port of launchsettings don't help
Moving file to another folder don't help
Deletion bin folder from main-solution don't help
i can access to old route (if it config) with postmen, but not with swagger or my blazor wasm frontend
with Postmen i arrived my breakpoint, with swagger or blazor wasm i get nothing
on all routes i get a log like: Request starting HTTP/1.1 GET https://localhost:44344/api/..., but on my specific route it is different
with postmen i get the log, but not with blazor wasm or swagger
I don't understand, where is the problem.
Edit 1: More Code
This not worked
[Route("api/identity/user")]
[ApiController]
public class UserController : CustomControllerBase<UserController>
{
private readonly IUserService _userService;
public UserController(IUserService userService, ILogger<UserController> logger) : base(logger)
{
_userService = userService;
}
/// <summary>
/// Get User Details
/// </summary>
/// <returns>Status 200 OK</returns>
[HttpGet()]
[AllowAnonymous]
public async Task<IActionResult> GetAll()
{
var users = await _userService.GetAllUsersAsync();
return Ok(users);
}
}
And this worked
[Route("api/identity/users")]
[ApiController]
public class UserController : CustomControllerBase<UserController>
{
private readonly IUserService _userService;
public UserController(IUserService userService, ILogger<UserController> logger) : base(logger)
{
_userService = userService;
}
/// <summary>
/// Get User Details
/// </summary>
/// <returns>Status 200 OK</returns>
[HttpGet()]
[AllowAnonymous]
public async Task<IActionResult> GetAll()
{
var users = await _userService.GetAllUsersAsync();
return Ok(users);
}
}

Related

NSwag + System.InvalidOperationException: The method 'get' on path '/Site' is registered multiple times

I just setup a new .NET Core 3.1 project, but I am having some issues when trying to use NSwag.AspNetCore, it has something to do with my controller but I can't figure it out. Here is my Site controller:
[Route("[controller]")]
[ApiController]
public class SiteController : BaseController
{
private readonly ISiteService _siteService;
public SiteController(ISiteService siteService, ILogger<SiteController> logger) : base(logger)
{
_siteService = siteService;
}
[HttpGet]
public IActionResult GetAllSites() => (ReadService(() => _siteService.Sites()));
[HttpGet("domainName/{domainName}")]
public IActionResult GetByDomainName(string domainName) => (ReadService(() => _siteService.Site(domainName)));
[HttpGet("status")]
public Task<IActionResult> GetStatusAsync() => (ReadServiceAsync(async () => await _siteService.GetApiStatusAsync()));
[HttpGet("lookupdata")]
public Task<IActionResult> GetLookupDataAsync() => (ReadServiceAsync(async () => await _siteService.GetLookupDataAsync()));
}
I am hitting /Site and it works fine via postman, it calls GetAllSites().
BUT for some reason I am getting the following error when trying to generate the swagger json (hit the SwaggerUI):
System.InvalidOperationException: The method 'get' on path '/Site' is registered multiple times.
at NSwag.Generation.AspNetCore.AspNetCoreOpenApiDocumentGenerator.AddOperationDescriptionsToDocument(OpenApiDocument document, Type controllerType, List`1 operations, OpenApiDocumentGenerator swaggerGenerator, OpenApiSchemaResolver schemaResolver)
at NSwag.Generation.AspNetCore.AspNetCoreOpenApiDocumentGenerator.GenerateForControllers(OpenApiDocument document, IGrouping`2[] apiGroups, OpenApiSchemaResolver schemaResolver)
at NSwag.Generation.AspNetCore.AspNetCoreOpenApiDocumentGenerator.GenerateAsync(ApiDescriptionGroupCollection apiDescriptionGroups)
at NSwag.Generation.AspNetCore.AspNetCoreOpenApiDocumentGenerator.GenerateAsync(Object serviceProvider)
at NSwag.AspNetCore.OpenApiDocumentProvider.GenerateAsync(String documentName)
at NSwag.AspNetCore.Middlewares.OpenApiDocumentMiddleware.GenerateDocumentAsync(HttpContext context)
at NSwag.AspNetCore.Middlewares.OpenApiDocumentMiddleware.GetDocumentAsync(HttpContext context)
at NSwag.AspNetCore.Middlewares.OpenApiDocumentMiddleware.Invoke(HttpContext context)
I am not sure what I could be doing wrong here everything seems to be setup properly.
For what it's worth, I am also including the custom BaseController class if there is something wrong there:
[ApiController]
public abstract class BaseController : ControllerBase
{
private ILogger _logger;
protected BaseController(ILogger logger)
{
_logger = logger;
}
}
If I were to decorate GetAllSites with:
[HttpGet("AllSites")]
It will work, but I don't want to do that, I want to be able to get all sites when I hit /site
For each action you can specify the routes as follow:
[HttpGet]
[Route("{id:min(1)}/GetItems1", Name = "GetHotelFacilities")]
public async Task getItems1(){}
[HttpGet]
[Route("{id:min(1)}/GetItems2", Name = "GetHotelFacilities")]
public async Task getItems2(){}

Why does not working version in asp.net core controller

I want to use api version in my .net core project.Then search web and find that's solution.
Even though do exactly all solutions,but I can't get desired result.
So if any can help me,Please show me..
I add Microsoft.AspNetCore.Mvc.Versioning 4.0.0 Package in my project and ..
StartUp.cs
Then in my Controller Add Rout Attribute as Shown :
[ApiController]
[Authorize]
[Route("v{version:apiVersion}/[Controller]")]
[ApiVersion("1.0")]
public class SellerController : Controller
{
private readonly IBus _client;
private readonly string AppBaseUrl = MyHttpContext.AppBaseUrl;
//private readonly IGetUrl _globalUrl;
public SellerController(IBus client/*, IGetUrl globalUrl*/)
{
_client = client;
//_globalUrl = globalUrl;
}
[HttpGet("/Sellers/{SellerId}")] // Dashboard
public async Task<IActionResult> Info(long SellerId)
{
...
}
}
With these code I expected that I can send request to 'Info' method by this url :
But that's not working and get 404 error code status.. when I delete "/v1.0" from url and send request, that's working. I will be glad to help me .. Thanks
In your code, we can find that you applied [HttpGet("/Sellers/{SellerId}")] with route
template begin with / to Info action method, which don't get combined with route templates applied to the controller. To make request to 'Info' method, you could use below URL.
https://localhost:5090/sellers/17
I expected that I can send request to 'Info' method by this url : https://localhost:5090/v1.0/sellers/17
To achieve your requirement, you can try to modify the code like below.
[HttpGet("/v{version:apiVersion}/Sellers/{SellerId}")]
public async Task<IActionResult> Info(long SellerId)
{
//...
//for testing purpose
return Ok(SellerId);
}
Test Result
Update:
If you'd like to include v{version:apiVersion} in route template of controller level attribute routing, you can try to apply [HttpGet("{SellerId}")] to Info action method and make request with https://localhost:5090/v1.0/seller/17.
[ApiController]
[Authorize]
[Route("v{version:apiVersion}/[Controller]")]
[ApiVersion("1.0")]
public class SellerController : Controller
{
[HttpGet("{SellerId}")] // Dashboard
public async Task<IActionResult> Info(long SellerId)
{
//...

IdentityUser not serializing Web Api

Not sure what is going on here.
I am exposing the Identity functionality through a Web API project. The CRUD aspect will be exposed to an admin app and the login, registration in a public facing app.
Right now I am just trying to return a list of all users in the database through a Web Api controller action. I am getting nothing output to the response, but I do get back data from the service:
/// <summary>
///
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("")]
public async Task<IHttpActionResult> GetAllUsers()
{
var model = await _userService.GetAllUsers(); //<---Gets List<AppUser> here?
return Ok(model);
}
This action shows nothing on fiddler or Postman?
Any ideas?
public class AppUser : IdentityUser
{
public DateTime Created { get; set; }
}
Is there something special about the IdentityUser class that prevents it from being serialized?
Here is the web api serialization config:
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
config.Formatters.Add(new JsonFormatter());
}
public class JsonFormatter : JsonMediaTypeFormatter
{
public JsonFormatter()
{
this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
this.SerializerSettings.Formatting = Formatting.Indented;
}
public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
{
base.SetDefaultContentHeaders(type, headers, mediaType);
headers.ContentType = new MediaTypeHeaderValue("application/json");
}
}
Found my answer. The IdentityUser class is not really meant to be exposed over an API; lots of sensitive data and all.
However this is will sit behind a firewall and I do not feel like writing a DTO and mapper just to make this work.
The answer is explained here
Basically you just need to override the properties you want exposed and decorate them with a DataMember attribute for serialization.

Query the authenticated user object too often within a http request

I am using asp.net core mvc with asp.net identity.
My ApplicationUser has a property: Country => 'GB' or 'FR' etc...
I want to set the System.Threading.Thread.CurrentThread.CurrentCulture to the value read from the applicationUser.Country. to display all datetime/number values correctly in my views as set by the user.
Thus I created this action filter:
public class LanguageActionFilter : ActionFilterAttribute
{
private readonly ILogger _logger;
private UserManager<ApplicationUser> _userManager;
public LanguageActionFilter(ILoggerFactory loggerFactory, UserManager<ApplicationUser> userManager)
{
_logger = loggerFactory.CreateLogger("LanguageActionFilter");
_userManager = userManager;
}
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
var user = await _userManager.GetUserAsync(context.HttpContext.User);
Thread.CurrentThread.CurrentCulture = new CultureInfo(user.Country);
await base.OnActionExecutionAsync(context, next);
}
}
On the action/controller where this actionfilter is set I also run this code:
public async Task<IActionResult> Index()
{
var user = await this.userManager.GetUserAsync(User);
var todos = await service.GetTodosAsync(user.Id);
return View(todos);
}
At the moment I call the this.userManager.GetUserAsync(User);
TWO TIMES !
Then I thought about passing the user object to the
context.HttpContext.Items.Add("applicationUser", user);
and grab this user object again within the Index() action method:
var user = (ApplicationUser)base.HttpContext.Items["applicationUser"];
That worked, but is that a good idea? Do you see any problems with that approach?
What you did is fine...
I'm quoting from the definition of the HttpContext class :
/// <summary>
/// **Gets or sets a key/value collection that can be used to share data within the scope of this request.**
/// </summary>
public abstract IDictionary<object, object> Items { get; set; }
Edit : It seems ef core doesn't support first level cache. So my idea went for nothing
Your code works, but i think you won't gain considerable performance.
You probably use aspnet identity with entity framework. Since ef supports first level cache. , if you call this.userManager.GetUserAsync(User); more than one, ef retrieves user entity from database only once. As a result two ways approximately have same effect for performance. I wouldn't use HttpContext.Items for your case.

Unable to get Scoped Service in aspnetcore 1 - RC1 to work

My scoped service for some reason seems to be generating different instances of the same class when I try to access it in 2 middlewares within the same request.
Scenario: I am adding a scoped service as such:
public interface ISimplyRecorder
{
void AddInfo(string key, string value);
Dictionary<string, string> GetAllInfo();
}
public class SimplyCoreRecorderService : ISimplyRecorder
{
private Dictionary<string,string> data;
public SimplyCoreRecorderService()
{
data = new Dictionary<string, string>();
}
public void AddInfo(string key,string value)
{
data.Add("",value);
}
public Dictionary<string,string> GetAllInfo()
{
return data;
}
}
and then the following in startup.cs
services.AddScoped<ISimplyRecorder,SimplyRecorderService>();
now I am calling this service in the constructor of a sample Middleware. I am able to access the service with a new instance and add data into it and then I call await _next(context). However, when I am calling the service in my HomeController, MVC which follows the middleware above, I seem to be getting a new instance of the service even though it's the same request.
HomeController:
ISimplyRecorder _simply;
private IHostingEnvironment _env;
public HomeController(IHostingEnvironment env,ISimplyRecorder simply)
{
_simply = simply;
_env = env;
}
public IActionResult Index()
{
_simply.AddInfo("Home:Action","resulted in index action");
return View();
}
complete code available at: https://github.com/muqeet-khan/SimplyCore if someone wants to give it a go.
Middlewares are instantiated only once when it's first involved, then all the following requests are handled by that middleware instance. NOT a new middleware instance for each request.
You get your ISimplyRecorder in the constructor of the middleware and "cache" it as a private readonly variable. This means the middleware will get the ISimplyRecorder instance of the first request, then keep adding data to that instance for all the following requests rather than the new ISimplyRecorder instance for the following requests which you get in HomeController.
To solve it, you need to get ISimplyRecorder instance from the Invoke method of the middleware.
// using Microsoft.Extensions.DependencyInjection;
public async Task Invoke(HttpContext httpContext)
{
ISimplyRecorder recoder = httpContext.RequestServices.GetRequiredService<ISimplyRecorder>();
}
EDIT:
The comment of Juergen is correct, I tried it out. You may also just write like this:
public async Task Invoke(HttpContext httpContext, ISimplyRecorder recorder)
{
// recorder is from DI
}