Web API cant find apicontroller - c#

I'm trying to build a small application, a api to get data with entity framework and pas out to json with web api but get the error: {"Message":"No HTTP resource was found that matches the request URI 'http://localhost:61267/api/GetCarousel'.","MessageDetail":"No type was found that matches the controller named 'GetCarousel'."}
Call link: http://localhost:61267/api/GetCarousel
I have learn when goggled that it seem to be many solutions to this but non seems to fit mine.
WebApiConfig file
public class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.EnableCors();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
}
}
GetCarousel.cs Controller file
This is generated from database with help of Entity Framework
namespace MustWebAPI.Controller
{
public class GetCarousel : ApiController
{
private MustTestEntitie db = new MustTestEntitie();
// GET: api/GetCarousel
public IQueryable<GetCarousel_Result> GetGetCarousel_Result()
{
return db.GetCarousel_Result;
}
// GET: api/GetCarousel/5
[ResponseType(typeof(GetCarousel_Result))]
public IHttpActionResult GetGetCarousel_Result(int id)
{
GetCarousel_Result getCarousel_Result = db.GetCarousel_Result.Find(id);
if (getCarousel_Result == null)
{
return NotFound();
}
return Ok(getCarousel_Result);
}
// PUT: api/GetCarousel/5
[ResponseType(typeof(void))]
public IHttpActionResult PutGetCarousel_Result(int id, GetCarousel_Result getCarousel_Result)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != getCarousel_Result.Id)
{
return BadRequest();
}
db.Entry(getCarousel_Result).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!GetCarousel_ResultExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
// POST: api/GetCarousel
[ResponseType(typeof(GetCarousel_Result))]
public IHttpActionResult PostGetCarousel_Result(GetCarousel_Result getCarousel_Result)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.GetCarousel_Result.Add(getCarousel_Result);
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = getCarousel_Result.Id }, getCarousel_Result);
}
// DELETE: api/GetCarousel/5
[ResponseType(typeof(GetCarousel_Result))]
public IHttpActionResult DeleteGetCarousel_Result(int id)
{
GetCarousel_Result getCarousel_Result = db.GetCarousel_Result.Find(id);
if (getCarousel_Result == null)
{
return NotFound();
}
db.GetCarousel_Result.Remove(getCarousel_Result);
db.SaveChanges();
return Ok(getCarousel_Result);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool GetCarousel_ResultExists(int id)
{
return db.GetCarousel_Result.Count(e => e.Id == id) > 0;
}
}
}

You should rename the class from GetCarousel to GetCarouselController as this is the convention for web api routing.
As a side note, it may also be preferable to rename it to something more appropriate such as "CarouselController", typically "GetCarousel" is much more appropriate as the name of an action, not a controller.

Related

Why Visual Studio automatically creates ApiController with all async methods? How to create ApiController with sync methods in it?

I have created a asp.net core webapi controller named StudentsController.cs using the functionality provided by Visual Studio which is API Controller with actions,using Entity Framework. It implements all the controller methods with return type async Task<ActionResult<>> which is asynchronous method implementation and it is auto generated by Visual Studio
Question is Why it creates all the methods async by its own and how can I create all the methods synchronously using the same auto generate feature of Visual Studio?
async example of controller
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Students.Models;
namespace Students.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class StudentsController : ControllerBase
{
private readonly StudentContext _context;
public StudentsController(StudentContext context)
{
_context = context;
}
// GET: api/Students
[HttpGet]
public async Task<ActionResult<IEnumerable<Student>>> GetStudents()
{
return await _context.Students.Include(d => d.Department).ToListAsync();
}
// GET: api/Students/5
[HttpGet("{id}")]
public async Task<ActionResult<Student>> GetStudent(int id)
{
var student = await _context.Students.Include(d => d.Department).FirstOrDefaultAsync(i => i.SId == id);
if (student == null)
{
return NotFound();
}
return student;
}
// PUT: api/Students/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://aka.ms/RazorPagesCRUD.
[HttpPut("{id}")]
public async Task<IActionResult> PutStudent(int id, Student student)
{
if (id != student.SId)
{
return BadRequest();
}
_context.Departments.Update(student.Department);
await _context.SaveChangesAsync();
_context.Entry(student).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!StudentExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return Ok();
}
//[HttpPut]
//public async Task<IActionResult> PutStudent(Student student)
//{
// _context.Departments.Update(student.Department);
// await _context.SaveChangesAsync();
// _context.Entry(student).State = EntityState.Modified;
// try
// {
// await _context.SaveChangesAsync();
// }
// catch (DbUpdateConcurrencyException)
// {
// if (!StudentExists(student.SId))
// {
// return NotFound();
// }
// else
// {
// throw;
// }
// }
// return Ok();
//}
// POST: api/Students
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://aka.ms/RazorPagesCRUD.
[HttpPost]
public async Task<ActionResult<Student>> PostStudent(Student student)
{
_context.Students.Add(student);
await _context.SaveChangesAsync();
return CreatedAtAction("GetStudent", new { id = student.SId }, student);
}
[HttpPost]
[Route("StudentList")]
public async Task<ActionResult<Student>> PostStudentList([FromBody] List<Student> student)
{
try
{
foreach (Student s in student)
{
_context.Students.Add(s);
}
_context.SaveChanges();
return CreatedAtAction("GetStudents", student, _context.Students.Include(d => d.Department));
}
catch(Exception ex)
{
return BadRequest();
}
}
// DELETE: api/Students/5
[HttpDelete("{id}")]
public async Task<ActionResult<Student>> DeleteStudent(int id)
{
var student = await _context.Students.FindAsync(id);
if (student == null)
{
return NotFound();
}
_context.Students.Remove(student);
await _context.SaveChangesAsync();
return student;
}
private bool StudentExists(int id)
{
return _context.Students.Any(e => e.SId == id);
}
}
}
sync example of controller
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CourseCRUD.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace CourseCRUD.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class SubjectController : Controller
{
private readonly CourseContext _context;
public SubjectController(CourseContext context)
{
_context = context;
}
[HttpGet]
// GET:api/subject
public IActionResult GetSubjects()
{
try
{
var subjects = _context.subjects.ToList();
return Ok(subjects);
}
catch
{
return BadRequest();
}
}
[HttpPost]
public IActionResult AddSubject([FromBody]Subject subject)
{
try
{
_context.subjects.Add(subject);
_context.SaveChanges();
return CreatedAtAction("GetSubjets", subject);
}
catch
{
return BadRequest();
}
}
[HttpGet("{id}")]
public IActionResult GetSuject(int id)
{
try
{
var subject = _context.subjects.Find(id);
return Ok(subject);
}
catch
{
return BadRequest();
}
}
[HttpPut("id")]
[HttpPut("{id}")]
public IActionResult UpdateSubject(int id, Subject subject)
{
if (id != subject.SubjectId)
{
return BadRequest();
}
_context.Entry(subject).State = EntityState.Modified;
try
{
_context.SaveChanges();
return Ok(subject);
}
catch (DbUpdateConcurrencyException)
{
if (!SubjectDetailExist(id))
{
return NotFound();
}
else
{
throw;
}
}
}
private bool SubjectDetailExist(int id)
{
throw new NotImplementedException();
}
[HttpDelete("{id}")]
public IActionResult DeleteSubject(int id)
{
var result = _context.subjects.Find(id);
if (result == null)
{
return NotFound();
}
_context.subjects.Remove(result);
try
{
_context.SaveChanges();
return Ok(result);
}
catch
{
return BadRequest();
}
}
}
}```
it's a long time since I did anything with t4 templates so a bit rusty but you should perhaps start here
https://learn.microsoft.com/en-us/visualstudio/modeling/code-generation-and-t4-text-templates?view=vs-2019
You specify templates in text files and use rules to generate the required code.
<## output extension=".cs" #>
<## assembly name="System.Xml" #>
<#
System.Xml.XmlDocument configurationData = ...; // Read a data file here.
#>
namespace Fabrikam.<#= configurationData.SelectSingleNode("jobName").Value #>
{
... // More code here.
}
Depending on the values in the XML file, the generated .cs file would resemble the following:
namespace Fabrikam.FirstJob
{
... // More code here.
}
I don't know if controller scaffolding uses t4 templates but it wouldn't suprise me.. or something similar.
The async actions are generated by templates of scaffolding which locates in path similar to C:\ProgramFiles\dotnet\sdk\NuGetFallbackFolder\microsoft.visualstudio.web.codegenerators.mvc\2.0.3\Templates
You could change the template manually.Refer to
https://stackoverflow.com/a/39503291/10158551

Attribute Routing In Asp.net Core Web api

I try to start asp.net core web api routing attribute as default route but when I access routing with parameter, I could not get any response
[Route("api/[controller]")]
[ApiController]
public class WarehousesController : ControllerBase
{
private readonly ApplicationDbContext _context;
public WarehousesController(ApplicationDbContext context)
{
_context = context;
}
//http://localhost:2394/api/Warehouses/Project/1 (Not working)
[HttpGet("Project/{projectId}")]
public async Task<IActionResult> GetWarehouseByProjectId([FromRoute] int projectId)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var warehouse = await _context.warehouses.Include(x => x.Projects).Where(y => y.Projects.FirstOrDefault().ProjectId == projectId).ToListAsync();
if (warehouse == null)
{
return NotFound();
}
return Ok(warehouse);
}
}
Try with this one .This works fine for me
[HttpGet("Project/{projectId}")]
public async Task<IActionResult> GetWarehouseByProjectId([FromRoute] int projectId)
{
if (!ModelState.IsValid)
{
return BadRequest("Invalid state");
}
var warehouse =await _context.warehouses.FindAsync(projectId);
if (warehouse == null)
{
return NotFound("not found");
}
return Ok(warehouse);
}

404 Error With MVC.NET Web API

I'm making a very simple Web API using MVC.NET to retrieve values from the following database:
CREATE TABLE [dbo].[Rates] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Code] VARCHAR (3) NOT NULL,
[Name] VARCHAR (50) NOT NULL,
[Rate] DECIMAL (5, 2) NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
);
For whatever reason that I do not understand, whenever I compile my solution and navigate to localhost:xxxxx/api or api/Rates (my controller), I get the following error:
Server Error in '/' Application
The Resource cannot be found. (A Http 404 error)
I do not understand why this is happening, as it's a freshly built api application, using Entity Framework.
Below are my controllers and WebApiConfig classes. Perhaps something in one of those is amiss?
WebApiConfig:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Web.Http;
using Microsoft.Owin.Security.OAuth;
using Newtonsoft.Json.Serialization;
using System.Net.Http.Headers;
namespace ExchangeService
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "localhost:63484/api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Formatters.Remove(config.Formatters.XmlFormatter);
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
}
}
}
ValuesController (Left as default)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace ExchangeService.Controllers
{
[Authorize]
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
public string Get(int id)
{
return "value";
}
// POST api/values
public void Post([FromBody]string value)
{
}
// PUT api/values/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/values/5
public void Delete(int id)
{
}
}
}
And finally, my Rates controller:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Description;
using ExchangeService.Models;
namespace ExchangeService.Controllers
{
public class RatesController : ApiController
{
private ExRatesDBEntities db = new ExRatesDBEntities();
// GET: api/Rates
public IQueryable<Rate> GetRates()
{
return db.Rates;
}
// GET: api/Rates/5
[ResponseType(typeof(Rate))]
public IHttpActionResult GetRate(int id)
{
Rate rate = db.Rates.Find(id);
if (rate == null)
{
return NotFound();
}
return Ok(rate);
}
// PUT: api/Rates/5
[ResponseType(typeof(void))]
public IHttpActionResult PutRate(int id, Rate rate)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != rate.Id)
{
return BadRequest();
}
db.Entry(rate).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!RateExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
// POST: api/Rates
[ResponseType(typeof(Rate))]
public IHttpActionResult PostRate(Rate rate)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Rates.Add(rate);
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = rate.Id }, rate);
}
// DELETE: api/Rates/5
[ResponseType(typeof(Rate))]
public IHttpActionResult DeleteRate(int id)
{
Rate rate = db.Rates.Find(id);
if (rate == null)
{
return NotFound();
}
db.Rates.Remove(rate);
db.SaveChanges();
return Ok(rate);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool RateExists(int id)
{
return db.Rates.Count(e => e.Id == id) > 0;
}
}
}
The only other point of interest I can think of, is that this application is running from an external hard drive. I can't think of any reason why this should be an issue, but thought it would be worth noting. Thanks.
For whatever reason that I do not understand, whenever I compile my solution and navigate to localhost:xxxxx/api or api/Rates (my controller), I get the following error:
Server Error in '/' Application
The Resource cannot be found. (A Http 404 error)
In the first case it cause, because you didn't specify API controller, in the second case, because you didn't specify method of API controller.
Try to call it as http://localhost:63484/api/Rates/GetRates
UPDATE:
Looks like you haven't registered your routes correctly, since you are using both MVC and Web API, so try these configurations:
WebApiConfig class:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
RouteConfig class:
public static class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
And then call them in your Global.asax class:
protected void Application_Start()
{
...
//next line registers web api routes
GlobalConfiguration.Configure(WebApiConfig.Register);
...
//next line registers mvc routes
RouteConfig.RegisterRoutes(RouteTable.Routes);
...
}
I don't believe you need to list the port.
Change the following in your WebApiConfig:
routeTemplate: "localhost:63484/api/{controller}/{id}"
to
routeTemplate: "api/{controller}/{id}"
Try also renaming:
GetRates() to Get()
and calling:
http://localhost:63484/api/Rates
For a rate with an Id you will need to make the following changes:
// GET: api/Rates/5
[ResponseType(typeof(Rate))]
public IHttpActionResult GetRate(int id)
{
Rate rate = db.Rates.Find(id);
if (rate == null)
{
return NotFound();
}
return Ok(rate);
}
to
// GET: api/Rates/5
[ResponseType(typeof(Rate))]
public IHttpActionResult Get(int id)
{
Rate rate = db.Rates.Find(id);
if (rate == null)
{
return NotFound();
}
return Ok(rate);
}
Actually all your Actions in your RateController need to be renamed. Use the same naming convention as you did in your ValuesController. WepAPI is meant to operate off of the named Actions Get(), Put(), Post() etc.

WebApi routing - many GET methods

I have the following (standard) WebApiConfig:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
and the following api controller:
[RoutePrefix("api/books")]
public class BooksController : ApiController
{
// GET api/Books
[Route("")]
public IQueryable<string> GetBooks()
{
return null;
}
// GET api/Books/5
[Route("{id:int}")]
public async Task<IHttpActionResult> GetBook(int id)
{
return Ok();
}
[Route("{id:int}/details")]
public async Task<IHttpActionResult> GetBookDetail(int id)
{
return Ok();
}
[Route("abc")]
public IQueryable<string> GetBooksByGenre(string genre)
{
return null;
}
[Route("~api/authors/{authorId}/books")]
public IQueryable<string> GetBooksByAuthor(int authorId)
{
return null;
}
}
It found appropriate method when I call
api/books
api/books/1
api/books/1/details
but it can't find api/books/abc.
If I change [Route("abc")] to [Route("{genre}")] it works (pass abc as genre parameter).
But I need to have many GET methods with different names.
What did I do wrong?
Try
// GET api/Books/genres/horror
[Route("genres/{genre}")]
public IQueryable<string> GetBooksByGenre(string genre)
{
return null;
}
Or even
// GET api/genres/horror/books
[Route("~api/genres/{genre}/books")]
public IQueryable<string> GetBooksByGenre(string genre)
{
return null;
}

WEB API 2 controller can't access the resource

I have a webforms project that supports MVC. I have created a WEB API 2 controller that used a model class which was generated using EF database first to convert SQL table into entity model. when I launch my application, the controller doesn't work as expected. I get the following when try to access the api:
HTTP Error 404.0 - Not Found
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
My Controller class is as following:
namespace YuClone.Controllers {
public class VideosController : ApiController
{
private YuCloneContext db = new YuCloneContext();
// GET: api/Videos
public IQueryable<video> Getvideos()
{
return db.videos;
}
// GET: api/Videos/5
[ResponseType(typeof(video))]
public IHttpActionResult Getvideo(long id)
{
video video = db.videos.Find(id);
if (video == null)
{
return NotFound();
}
return Ok(video);
}
// PUT: api/Videos/5
[ResponseType(typeof(void))]
public IHttpActionResult Putvideo(long id, video video)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != video.videoid)
{
return BadRequest();
}
db.Entry(video).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!videoExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
// POST: api/Videos
[ResponseType(typeof(video))]
public IHttpActionResult Postvideo(video video)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.videos.Add(video);
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = video.videoid }, video);
}
// DELETE: api/Videos/5
[ResponseType(typeof(video))]
public IHttpActionResult Deletevideo(long id)
{
video video = db.videos.Find(id);
if (video == null)
{
return NotFound();
}
db.videos.Remove(video);
db.SaveChanges();
return Ok(video);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool videoExists(long id)
{
return db.videos.Count(e => e.videoid == id) > 0;
}
} }
What can be done to fix this?
Edit:
This is how the route is configured in WebApiConfig :
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
which is registered in application_start method in Global.aspx as :
RouteConfig.RegisterRoutes(RouteTable.Routes);
The URL I'm using to access the resource is :
http://localhost:5958/api/videos
You need to register your WebAPI routes in Global.asax.cs:
GlobalConfiguration.Configure(WebApiConfig.Register);
You are not registering the WebAPI routes.
RouteConfig.RegisterRoutes(RouteTable.Routes);
This code only registers MVC controller routes. For Web API, you need to register web api routes by calling the class you mentioned -
var config = GlobalConfiguration.Configuration;
WebApiConfig.Register(config); //register api routes
RouteConfig.RegisterRoutes(RouteTable.Routes);
This should work for you.
Make sure you are calling the RouteConfig.RegisterRoutes after the WebApiConfig.Register. Like this:
System.Web.Http.GlobalConfiguration.Configure(WebApiConfig.Register);
RouteConfig.RegisterRoutes(RouteTable.Routes);

Categories

Resources