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.
Related
I have an ASP.NET MVC app, in which I use a custom authorization filter throughout several parts of the app.
[MyCustomAuthorize]
class MyController
{
}
This has worked well for a long while.
Now I want to add another piece to the app which is basically a pre-built React app - a subfolder structure containing an index.htm file, JS, CSS, and other resource files.
When a user navigates to this sub-app, I want them to be sent through the same authorization process implemented in my custom authorization attribute. But naturally, since it's a static .htm file, I have no way of applying any attribute to it.
I tried to resolve this by placing it behind an MVC controller:
using MyApp.Filters;
using System.Web.Mvc;
namespace MyApp.Controllers
{
[MyCustomAuthorize]
public class SubAppController : Controller
{
public ActionResult Index()
{
return File("~/SubApp/index.htm", "text/html");
}
}
}
but it seems that what happens if I navigate to https://mydomain/SubApp/ is that IIS finds the index.htm file and serves that up instead of the request going through the controller.
If I rename the index.htm to something else and try to serve it this way:
using MyApp.Filters;
using System.Web.Mvc;
namespace MyApp.Controllers
{
[MyCustomAuthorize]
public class SubAppController : Controller
{
public ActionResult Index()
{
return File("~/SubApp/subapp.htm", "text/html");
}
}
}
then it seems IIS sees the https://mydomain/SubApp/ request as an attempt to access the physical SubApp/ folder, and returns a 403 response.
I realize I could get around these two issues by physically placing the sub-app contents in a folder with a different name from the controller, but that would introduce yet another problem where all of the sub-app's resource files (CSS, JS, etc.) are no longer in a sub-path of the path where the sub-app is being accessed (i.e. the browser would be accessing https://mydomain/SubApp/ and the .css would be in https://mydomain/SubAppFiles/styles.css). I would like to avoid that situation if possible, and have all of the resources (both physically and conceptually) contained within the SubApp/ folder.
Is there a relatively simple way to get this to work nicely without too much overhaul to the main app?
I think the ideal situation would be to find some way to have IIS not try to handle the request to https://mydomain/SubApp/ (just that one path and nothing else) and allow the ASP.NET app to handle it, but as of yet, I've been unsuccessful in finding a way to do that.
I'm new to asp.net mvc and web api. I'm reading a book which says:
ASP.NET MVC uses: System.Web.HttpRequest
and Web API Equivalent is System.Net.Http.HttpRequestMessage
and below is a picture that describes the request and result flow of web api
So my question is, how does hosting environment(which will typically be IIS) know that it should create a HttpRequestMessage object to represent the request from the client? I mean if the application is a MVC application, IIS should create a HttpRequest object instead of HttpRequestMessage, so how does IIS know which one to create?
As you can see from the picture you posted, the HttpRequestMessage exists only inside the "hosting" environment, web browser client does not know anything about that.
In the "hosting" world, IIS app pool is running the code you have built and deployed which knows very well wich framewok you are using as your code also contains the using assemblies you listed, System.Web... or System.Net...
Consider that even if you have shown separation between hosting, Controller and Action, all of that is running in same App Pool in IIS which, again, runs your code so knows what it is about as your IL assemblies were built from your specific source code.
I am not sure if I understand your question but this might be what you're looking for:
I mean if the application is a MVC application, IIS should create a
HttpRequest object instead of HttpRequestMessage, so how does IIS know
which one to create?
You must remember how you differentiate between a normal MVC Controller and a Web API Controller...
WebAPI Controllers enforces this annotation [ApiController] and must inherits from ControllerBase:
[ApiController]
public class PeopleController : ControllerBase {
//Your API methods here
}
A normal MVC Controller only inherits from Controller base class:
public class PeopleController : Controller {
//Your Action methods here...
}
Those already create configuration for your APP which becomes easier for you Hosting environment to know what is going and what to return when.
I hope you find this helpful.
I am trying to learn Web API and MVC. I, initially created a basic MVC project. Now, in the controllers folder ,I added a WebAPI controller.
In the WebAPI controller, I added the below code
public class SampleController : ApiController
{
[HttpPost]
public IHttpActionResult SampleData()
{
var userID = User.Identity.GetUserId();
return Ok();
}
}
The Method User.Identity.GetUserId() works fine in MVC.
I searched about on SO and found the following thread
User.Identity.GetUserId() method not working in a Web Api 2 Controller
This was not that helpful for me, as in my case I have added the API controller as part of the MVC project itself in the controllers folder.I have not created a separate project for WebAPI.
The above mentioned thread talks about the accesstoken already being present in code , whereas in my case, I dont see that code anywhere, as I just added only a single web api controller.
I am using POSTMAN for calling the API.
I have also looked at the following link
https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/individual-accounts-in-web-api
In this case too, a separate WebAPI project is being talked about and not a single controller.
If I am mistaken somewhere, kindly guide me on the same.
I'm trying to pass configuration values to bootstrap a single page AngularJs app hosted within an MVC app that utilises WebApi (see below from the Razor view, this is achieved by inheriting a BasePage and dependency injecting a Serializer/FinancialYears service).
<script>
var angularInitConfig = #Html.Raw(Serializier.Serialize(new {
financialYears = FinancialYearsService.GetFinancialYears()
}));
</script>
This works perfectly, however I would really like to be able to extend it to include the routes from my WebApi app to avoid having to configure the endpoints in both the WebApi app AND the AngularJs app individually.
Having poked around in the RouteTable.Routes class I can see that the information I require is available and accessible from within the view, however I've been unable to extract it.
So what I'd ideally like to do is generate a collection of objects as defined below from the RouteTable.Routes class, serialize them and spit them out in the bootstrap config for the AngularJS app to consume.
new {
name = "SomeService",
route = "api/{financialYearId}/someservice",
method = "POST"
}
Does anybody have an idea how to extract this information from RoutesTable.Routes? Is there an easier way to generate the data required?
NB. All WebApi routes are configured explicitly using the Routes attribute as such:
[HttpGet]
[Route("api/{financialYearId}/someservice")]
If you create default template asp.net Mvc or WebAPi using Visual Studio, you will get Help in Folder > Areas\HelpPage...and if you access your application in : Http://yourportapplication/api/Help if project webapi...
then, you can see the code how to get information...just for started what you looking for,....
I have an asp.net website. The Admin panel is located here:
mysite.com/manager
I want to change this to:
mysite.com/admin
There is no file named manager in the website files and I'm unsure how to make this change or locate the manager source file.
Firstly, it's unlikely to be related to a database in anyway.
Sounds like your project is using MVC and Routing:
The ASP.NET Routing module is responsible for mapping incoming browser requests to particular MVC controller actions
If so, your web project will have a folder called "Controllers" and within that there will be a file called "ManagerController.cs".
Within this file, you'll see a method that looks like:
public virtual ActionResult Index()
{
// some code maybe
return View();
}
This is what will be called when that URL is hit.
You may also want to search for a file called RouteConfig.cs, which is located in the App_Start folder, where any non-standard routes will be configured.
To make the change, you can copy and rename ManagerController.cs to AdminController.cs and MVC will work it's magic as the default routing will search for that file instead.