I'm working on a Web MVC project and inside it I want to have some api controllers for external apps to use.
My API controllers have the ApiController attribute on them.
Unfortunately, Swashbuckle picks up ALL the controllers/actions.
Is there a way to tell it to only look for Api controllers?
Thank you.
You can put this in the controller you want to hide from Swashbuckle
[ApiExplorerSettings(IgnoreApi = true)]
public class UserController : Controller
Related
We are developing a new API version in our application, so that we basically have a
namespace Bla.V1.Controllers
[ApiController]
[ApiVersion("1")]
public partial class SampleController : ControllerBase {}
and a
namespace Bla.V2.Controllers
[ApiController]
[ApiVersion("2")]
public partial class SampleController : ControllerBase {}
We've also configured API versioning (AddApiVersioning), so that when somebody tries to access e.g. api/v3/sample/action, he will get a version not supported error response, provided by the API versioning middleware.
Now the V2 version is in development and we want to make it available only for the development stage. The controllers code will be deployed to production, we want however to disable the V2 version for production.
We would do it with a feature flag, but what should be done to hide the V2 controllers?
I was thinking:
Somehow do not register the V2 controllers. Didn't find a suitable option in AddControllers()
Set maximum version to V1 in the API versioning middleware. This works only for headers, doesn't block access to V2 controllers
I'm currently thinking about writing an authorization attribute that would deny access based on the feature flag status and apply it to V2 controllers. Is there a better and more elegant way to do this?
Well, in case somebody is interested at some point. Our controller code is autogenerated from a Swagger definition. So I added the following code to the generation template, which gets invoked in each controller method:
if (!this.IsV2Enabled())
{
var protocol = this.Request.IsHttps ? "https" : "http";
return this.BadRequest(new
{
error = new {
code = "UnsupportedApiVersion",
message = $"The HTTP resource that matches the request URI '{protocol}://{this.Request.Host}{this.Request.Path}' does not support the API version '1'."
}
});
}
I have a .NET Core project which includes MVC and a Web API in the same solution. I'm trying to connect those projects to each other but API's route and MVC's conflict.
I have an a tag like this,
<a asp-controller="Categories" asp-action="Update"
class="btn btn-primary" asp-route-categoryId="#category.Id">Update</a>
then this a tag generates a link like this
href="/api/Categories?categoryId=1"
My controllers and actions are using same names, I think that's why it happens, so I've changed the names then it worked. I can change the names but wonder why this happens. Are there different solutions?
one of the solutions could be using attribure routing. For example
api
[ApiController]
[Route("api/[controller]/[action]")]
public class CategoryController:ControllerBase
mvc
[Route("[controller]/[action]")]
public class CategoryController:Controller
or you can configure similar route templates in startup file.
We have an ASP.NET Core Web API running on .NET 5. It has got many controllers and routes that are sometimes protected via the Authorize attribute and sometimes they are public.
[ApiController]
[Route("[controller]")]
public class UserController : ControllerBase {
[HttpGet("me")]
public IActionResult GetMyPublicInformation()
{
// code...
}
[HttpGet("me")]
[Authorize]
public IActionResult GetMyPrivateInformation()
{
// code...
}
}
Well now I would like to publish these REST routes through different HTTP Routes, depending on the Authorization requirement. For example, the route GetPublicInformation does not require authorization. That route should be available under public/user/me. Whereas the method GetMyPrivateInformation does require authorization and should be published under the route secure/user/me.
Of coure, I am aware that I can define the route manually in the HttpGet attribute (i.e. [HttpGet("public/user/me")), but - besides that I'm lazy - it would be error prone because we have the information available twice: Once with in the manual route definition (HttpGet) and once in the Authorize attribute. So if someone forgets to change one of the two attributes, we get an inconsistency.
Question: What are my options to automate this URL rewriting (I'm thinking of middleware)? Are there any drawbacks you see using this approach? I have been fighting this idea because I don't like extra magic sauce in my codebase. I prefer explicity, that's why I'm going for the manual route naming right now...
By the way: I have to take this on me because of limitations in Microsoft's MSAL library. I believe I shouldn't have to do this because we host an OpenAPI definition on which routes are and which routes aren't authorized. That should be enough in most cases.
I'm trying to deploy my ASP.NET Core MVC Web App with Web API, i.e. I have both MVC and API controllers in the same folder.
It works fine on localhost but on IIS when I create a Virtual Directory, the path gets added to the domain.
I can find it using window.location.pathname
I can append the 'api/Get' and it works like (questions is my virtual directory)
http://example.com/questions/api/Question/GetAll
But when I navigate to other pages then then controller name also gets appended and then it causes issues.
e.g. if I navigate to the 'Question' page (QuestionController), the URL becomes
http://example.com/questions/newquestion/api/Question/Create
instead of
http://example.com/questions/api/Question/Create
How can I fix it?
Here is my Asp.Net core api.
[ApiController]
public class ScheduleController : ControllerBase
{
[HttpGet]
public List<PathologistSchedule> GetPathologistScheduleByDate(DateTime taskDate)
{
return pathologistRepository.GetPathologistScheduleByDate(taskDate).ToList();
}
}
I call this api from PathologistScheduleController's view using jquery.
Here's the error I get:
GET http://localhost:51434/PathologistSchedule/api/Schedule/?sort=&group=&filter=&taskDate=2020-11-13T21%3A16%3A47.507Z 404 (Not Found)
TIA.
A
If you have API and MVC projects in one solution you have to config your solution to run multiple projects.
You can use route attribute like this for each of your APIs
[Route("~/api/Question/GetAll")]
will give you Url http://example.com/api/Question/GetAll.
Or
[Route("~/api/Question/Create")]
will give Url http://example.com/api/Question/Create.
And it will not depend on the controller name or folder.
UPDATE because of the question update:
Use this code please:
public class ScheduleController : ControllerBase
{
[Route("~/api/Schedule/GetPathologistScheduleByDate/{taskDate?}")]
public List<PathologistSchedule> GetPathologistScheduleByDate(DateTime taskDate)
{
return pathologistRepository.GetPathologistScheduleByDate(taskDate).ToList();
}
}
for testing try this route in your browser:
http://localhost:51434/api/Schedule/GetPathologistScheduleByDate/2020-11-13T21%3A16%3A47.507Z
But basically for APIs you don't need to use any controller or action name. You can use any names you like, for example:
[Route("~/api/Pathologist/GetSchedule/{taskDate?}")]
or
[Route("~/api/GetPathologistSchedule/{taskDate?}")]
or even
[Route("~/api/{taskDate?}")]
The route just should be unique.
I added a variable in the 'appsettings.json' and 'appsettings.Development.json' called baseURL and had 'appsettings.json' set to '/VirtualDirectoryName/' and kept the one in 'appsettings.Development.json' as '/'.
Appended this variable when calling APIs.
My application has MVC controllers and WebApi controllers. Up to this point, I've been able to push any logic shared between the controllers into a BaseController and BaseApiController, respectively.
Now I have a situation where both an API controller and MVC controller are doing the same thing - registering a new user account. This process is a bit complex because I have a multi-tenant application, and looks something like this:
// MVCController : BaseController
public ActionResult Register(RegisterModel model) {
// see if the model is valid
// check and make sure the credentials check out with policy requirements
// add the user to the user table if they aren't already there
// create a tenancy
// assign cookie
}
Most of the actual work is pushed off into the service layer, but the calls and conditions take up about 20 lines of code that I'd rather not copy and paste into the analogous WebApi controller.
So I'm wondering if I can somehow have both my BaseController and BaseApiController inherit from a generic controller where I can put this auth code. What's the recommended approach here?
Unless I am missing something from your question, I would refactor that piece of code into a Util class that lives in your UI project. Then both your MVC controller and WebAPI controller can call it.
This approach is in-line with Composition over inheritance design principle.
If you cannot move the logic out into it's own library and then share it then I would probably see about calling the web api from mvc. See this post for an example on doing that: https://stackoverflow.com/a/13206631/426422