I have added an ASP.NET Web API to an ASP.NET MVC 5 web application project developed in Visual Studio 2019.
WebApiConfig:
public class WebApiConfig {
public static void Register(HttpConfiguration config) {
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Global.asax.cs:
public class MvcApplication : HttpApplication {
protected void Application_Start() {
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
GlobalConfiguration.Configure(WebApiConfig.Register);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
Api Controller Method:
// GET: api/Web
public IEnumerable<string> Get() {
return new string[] { "value1", "value2" };
}
When I hit https://localhost:44324/api/web the browser gives this error:
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /api/web
In MVC 5 routing you can try using attributing routing to overcome this error.
The solution is shown below.
API Controller Method:
//write this above the class and below namespace
[ApiController]
[Route("[controller]")]
// GET: api/Web
[HttpGet]
public IEnumerable<string> Get() {
return new string[] { "value1", "value2" };
}
When you hit https://localhost:44324/api/web but here "Web" is controller id it's not then you have to mention that first and then the method the browser will not give you an error:
Related
I have been working with .NET Core for only a few weeks. Now I have a question about a Web API that I created for a project.
I need to call an external API, however all the documentation I see is for applications with MVC. This means they have a main page, which I
don't have and don't want, because I just want to call this API on an new endpoint and to be consume on client side.
If I test the external API in postman it returns something like this:
postman response
I tried to follow along with the official documentation of Microsoft Call a Web API From a .NET Client (C#) however I get to a point where I'm not sure how to proceed.
I've create a model with a few of the result properties that I want to capture from the call to this endpoint shown in the first image and a simple controller that I want to be the final endpoint that return the information from this external API.
These are the things that I have already:
Model class Product:
namespace MyProyect
{
public class Product
{
public string Id { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public string Type { get; set; } = string.Empty;
}
}
Controller to consume the external API:
namespace MyProyect.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ThirdPartyAPIController : ControllerBase
{
static HttpClient client = new HttpClient();
[HttpGet]
static async Task<Product> GetProductsAsync(string path)
{
Product product = null;
HttpResponseMessage response = await client.GetAsync(path);
if (response.IsSuccessStatusCode)
{
product = await response.Content.ReadAsAsync<Product>();
}
return product!;
}
}
}
I don't really know how to proceed from here, this is all I can get from the documentation. I want this controller to be an endpoint that the user can consume. But this is not even appearing on the Swagger UI screen.
Is there an easy way to do this? Am I using an incorrect way?
First register a HttpClient for your Controller/Service
// In Startup.cs (5.0)
services.AddHttpClient<ThirdPartyAPIController>();
// ... or in Program.cs (6.0)
builder.Services.AddHttpClient();
Then inject the HttpClient and use it in the Controller method.
namespace MyProyect.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ThirdPartyAPIController : ControllerBase
{
// Let the `IHttpClientFactory` do the `HttpClient` handling
private HttpClient _client;
public ThirdPartyAPIController(HttpClient client)
{
_client = client;
}
[HttpGet]
// use `public` instead of `static`
// only this is then visible in Swagger UI
public async Task<Product> GetProductsAsync(string path)
{
Product product = null;
HttpResponseMessage response = await _client .GetAsync(path);
if (response.IsSuccessStatusCode)
{
product = await response.Content.ReadAsAsync<Product>();
}
return product!;
}
}
}
Like written in the code comment. You have to use public (not static) for the controller method to be registered and visible in Swagger UI.
Added an API controller to the project and it does not work. I get 404.
[Route("api/hlth")]
[ApiController]
public class hlth : ControllerBase
{
// GET: api/<hlth>
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/<hlth>/5
[HttpGet("{id}")]
public string Get(int id)
{
return "value";
}
}
Turns out I need to add
app.MapControllers();
that for some reason is not included in the default project configuration.
Filename: DemoController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace MVCEntityFramework.Controllers.Api
{
public class DemoController : ApiController
{
// GET api/<controller>
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/<controller>/5
public string Get(int id)
{
return "value";
}
// POST api/<controller>
public void Post([FromBody] string value)
{
}
// PUT api/<controller>/5
public void Put(int id, [FromBody] string value)
{
}
// DELETE api/<controller>/5
public void Delete(int id)
{
}
}
}
ScreenShot 1: https://i.stack.imgur.com/lDQ4O.png
ScreenShot 2: https://i.stack.imgur.com/ObG6W.png
Path Not Working:
https://localhost:44310/api/demo/get/2
https://localhost:44310/api/democontroller/get/2
Response:
HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
It'll work by convention so if you need to call Get by id just use https://localhost:44310/api/demo/2 without action name but you need to specify verb HttpGet if you need to call Post also you will call https://localhost:44310/api/demo with specify verb HttpPost
This is how to call post action using postman for example
or add [Route("[controller]")] attribute to class like
[Route("[controller]")]
public class DemoController : ApiController
{
// GET api/<controller>
[Route("Get")]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
so in this case you can add controller name to your endpoint like https://localhost:44310/api/demo/get/2
I'm new to Asp.net (.Net Core) Web API.
I made AdminController but when i requesting the URL localhost:52054/API/admin/get i got 404 not found on fiddler.
Here is my AdminController & Startup.cs
AdminController Image
namespace Api2017_1.Controllers
{
[Produces("application/json")]
[Route("api/Admin")]
public class AdminController : Controller
{
// GET: api/Admin
[HttpGet]
public async Task<BsonDocument> Get()
{
const string cs = "mongodb://localhost:27017";
var client = new MongoClient(cs);
var db = client.GetDatabase("store");
var coll = db.GetCollection<BsonDocument>("admins");
using (var cursor = await coll.Find(new BsonDocument()).ToCursorAsync())
{
while (await cursor.MoveNextAsync())
{
foreach(var doc in cursor.Current)
{
return doc;
}
}
}
return (BsonDocument)0;
}
Startup.cs Image
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseMvc();
}
}
Can anyone guide me where i made mistake.
Thanks in Advance.
You are requesting incorrect url. Use localhost:52054/API/admin instead with a request type as Get.
I have a routing problem in an MVC 6 web application : when I set route parameter in the controller used by default, application send a 404 error.
My routing configuration :
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Dashboard}/{action=Index}/{id?}");
});
My dashboard controller (application works) :
[Authorize]
public class DashboardController : Controller
{
public DashboardController()
{ }
[HttpGet]
public IActionResult Index() => View(new IndexViewModel());
}
Same dashboard controller (application responds a 404 error) :
[Authorize]
[Route("[controller]")]
public class DashboardController : Controller
{
public DashboardController()
{ }
[HttpGet]
[Route("[action]")]
public IActionResult Index() => View(new IndexViewModel());
}
The reason that this is occurring is that routes specified via routes.MapRoute only apply to controllers that are not using attribute based routing. Since your second example is using attribute based routing that controller can only be reached via the route specified in the attribute. So it can only be reached at /Dashboard/Index