简体   繁体   中英

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM