locked
My first Web API with a 404 error RRS feed

  • Question

  • User206383436 posted

    I am writing my first Web API and I have been stuck with a 404 error for a while. My  project is an ASP.NET MVC with a common controller and a view.

    This is the code for the Web API which is a controller inside the Controllers folder:

    namespace ChartsClubMVC.Controllers
    {
        public class waSeccArtGenController : ApiController
        {
    
            //GET : api/GetSeccArtGen
            public IHttpActionResult GetSeccArtGen()
            {
                String strMensaje = "";
                String strOrigen = "";
                String fecha = DateTime.Today.ToString("yyyy-MM-dd");
    
                SeccArtGeneralMVC objSeccArtGeneralMVC = new SeccArtGeneralMVC();
                var notas = objSeccArtGeneralMVC.ObtenerInfoMVC(ref strMensaje, ref strOrigen, "Notas", fecha, "", "SEC");
    
                return Ok(notas.ToList());
            }
        }
    }
    

    This is the jQuery code that calls the Web API. Its name is "SeccArtGen.js" and is located in "~/Scripts/SiteScripts/ folder". As you can see, there is an "error" catch with 2 "alerts" that display "404 not found". I am not displaying any valuable information here yet but only something that shows the loop is running.

    $(document).ready
        (
            function ()
            {
                $.ajax
                    ({
                        type: "GET",
                        dataType: "json",
                        url: "api/GetSeccArtGen/",
                        success: function(result)
                        {
                            alert('Here I am - Success');
                            DespliegaSeccArtGen(result);
                        },
                        error: function (xhr, ajaxOptions, thrownError) {
                            alert(xhr.status);
                            alert(thrownError);
                        }
                    });
            }
        );
    
    function DespliegaSeccArtGen(result)
    {
        var $mainContainerDiv = $("#mainContainer");
    
        for (var i = 0; i < result.length; i++)
        {
            var currentSeccArtGen = result[i];
            var $rowDiv = $("<div class='row'>").appendTo($mainContainerDiv);
            var $imagenDiv = $("<div class='col-lg-4 col-md-4 col-sm-4 col-xs-4>").appendTo($rowDiv);
            var $textoDiv = $("<div class='col-lg-8 col-md-8 col-sm-8 col-xs-8>").appendTo($rowDiv);
    
            var $imagen = $("Imagen " + i).appendTo($imagenDiv);
            var $texto = $("Texto " + i).appendTo($textoDiv);
        }
    }

    And finally this is the simple View located in the Views folder:

    @{
        ViewBag.Title = "Index";
    }
    <script src="~/Scripts/SiteScripts/SeccArtGen.js"></script>
    
    <h2>Sección de Artículos Generales</h2>
    
    <div id="mainContainer" class="container">
    
    </div>

    The Global.asax contains the following:

    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
    
        // Web API routes
        config.MapHttpAttributeRoutes();
    
        config.Routes.MapHttpRoute(
             name: "DefaultApi",
             routeTemplate: "api/{controller}/{action}/{id}",
             defaults: new { id = RouteParameter.Optional }
         );
    }

    I guess my problem has to do with the path to locate the Web API.

    I will very much appreciate your feedback.

    Best regards,
    Jorge Maldonado

    Tuesday, February 13, 2018 1:11 AM

Answers

  • User283571144 posted

    Hi JORGEMAL,

    Where port is the port number where my project runs. This way everything works correctly.
    One disadvantage of specifying the "localhost:port" number is that I need to modify it when uploading the website to the production server.
    Is there a way of getting rid of "localhost:port"?

    According to your description, I suggest you could add javascript in the layout view to get the application base url.

    Then you could directly use the application base url in the ajax.

    More details about how to get the application base url, you could refer to below codes:

        <script type="text/javascript">
     
        window.applicationBaseUrl = @Html.Raw(HttpUtility.JavaScriptStringEncode(
            new Uri(
                       new Uri(this.Context.Request.Url.GetLeftPart(UriPartial.Authority)),
                       Url.Content("~/")
                   ).ToString(), true));
        alert(window.applicationBaseUrl + "asd.html");
        </script>

    Result:

    Best Regards,

    Brando

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, February 15, 2018 4:27 AM

All replies

  • User1793353327 posted

    Hi, 

    You forgot to config api router.

        [Route("[controller]/[action]")]
        public class NewsController : BaseController

    Tuesday, February 13, 2018 1:16 AM
  • User206383436 posted

    I just tried setting routing using attributes without success. I basically modified the Web API controller and the Javascript file which consumes it as follows:

    namespace ChartsClubMVC.Controllers
    {
        public class waSeccArtGenController : ApiController
        {
    
            //GET : api/GetSeccArtGen
            [HttpGet]
            [Route("api/SeccArtGen")]
            public IHttpActionResult GetSeccArtGen()
            {
                String strMensaje = "";
                String strOrigen = "";
                String fecha = DateTime.Today.ToString("yyyy-MM-dd");
    
                SeccArtGeneralMVC objSeccArtGeneralMVC = new SeccArtGeneralMVC();
                var notas = objSeccArtGeneralMVC.ObtenerInfoMVC(ref strMensaje, ref strOrigen, "Notas", fecha, "", "SEC");
    
                return Ok(notas.ToList());
            }
        }
    }
    
    $(document).ready
        (
            function ()
            {
                $.ajax
                    ({
                        type: "GET",
                        dataType: "json",
                        url: "api/SeccArtGen/",
                        success: function(result)
                        {
                            alert('Here I am - Success');
                            DespliegaSeccArtGen(result);
                        },
                        error: function (xhr, ajaxOptions, thrownError) {
                            alert(xhr.status);
                            alert(thrownError);
                        }
                    });
            }
        );
    
    function DespliegaSeccArtGen(result)
    {
        var $mainContainerDiv = $("#mainContainer");
    
        for (var i = 0; i < result.length; i++)
        {
            var currentSeccArtGen = result[i];
            var $rowDiv = $("<div class='row'>").appendTo($mainContainerDiv);
            var $imagenDiv = $("<div class='col-lg-4 col-md-4 col-sm-4 col-xs-4>'").appendTo($rowDiv);
            var $textoDiv = $("<div class='col-lg-8 col-md-8 col-sm-8 col-xs-8>'").appendTo($rowDiv);
    
            var $imagen = $("<div>Imagen " + i).appendTo($imagenDiv);
            var $texto = $("<div>Texto " + i).appendTo($textoDiv);
    
        }
    }

    Tuesday, February 13, 2018 4:03 PM
  • User283571144 posted

    Hi JORGEMAL,

    I am writing my first Web API and I have been stuck with a 404 error for a while. My  project is an ASP.NET MVC with a common controller and a view.

    According to your description, I guess you may not register the web api in the "Global.asax" file.

    I suggest you could firstly add below line into the Application_Start() method.

            protected void Application_Start()
            {
                GlobalConfiguration.Configure(WebApiConfig.Register);
                AreaRegistration.RegisterAllAreas();
                FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
                RouteConfig.RegisterRoutes(RouteTable.Routes);
                BundleConfig.RegisterBundles(BundleTable.Bundles);
            }

    Also I have create a WebApiConfig class in the application start folder.

        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 }
                );
            }
        }

    Then it will work well.

    Besides, I suggest you could directly use the api url in the browser, it will directly show the result.

    I also create a test demo on my side, it works well.

    My api controller.

        public class waSeccArtGenController : ApiController
        {
            //GET : api/GetSeccArtGen
            [HttpGet]
            [Route("api/SeccArtGen")]
            public IHttpActionResult GetSeccArtGen()
            {
                String strMensaje = "";
                String strOrigen = "";
                String fecha = DateTime.Today.ToString("yyyy-MM-dd");
    
                //SeccArtGeneralMVC objSeccArtGeneralMVC = new SeccArtGeneralMVC();
                //var notas = objSeccArtGeneralMVC.ObtenerInfoMVC(ref strMensaje, ref strOrigen, "Notas", fecha, "", "SEC");
    
                return Ok("aaaa");
            }
        }

    Result:

    Best Regards,

    Brando

    Wednesday, February 14, 2018 7:15 AM
  • User206383436 posted

    Thanks Brando for the valuable information in your answer.

    In my case, the "Register" method was directly in the Global.asax file but I created the "WebApiConfig" class as you suggested to keep code more organized.
    I also tested the API from the web browser and it worked well but my problem is when the API is consumed from the Javascript code that is referenced in my View.
    Below you can see such code. For some reason the "url" parameter is not working correctly because I am shown the "404 Not Found" messages in the "error" event.

    I also tested creating 2 "html" web pages (including a reference to the Javascript file in both of course): one in the main project folder and one in the "Content" folder of my MVC project. 
    Such a test shows the following results:
    * The Web API is successfuly executed from the "html" page located in the project´s root folder.
    * I get the same error "404 Not Found" when the API is consumed from the web page located in the "Content" folder.

    So, the path/location of the View and the HTML file that references the Javascript code has some effect here because the Web API is consumed successfully when the HTML is placed in the project´s root folder, but there is a 404 error if placed somewhere else.

    $(document).ready
    ( function () { $.ajax ({ type: "GET", dataType: "json", url: "api/SeccArtGen/", success: function(result) { alert('Here I am - Success * ' + result.length + ' * '); DespliegaSeccArtGen(result); }, error: function (xhr, ajaxOptions, thrownError) { alert(xhr.status); alert(thrownError); } }); } );

    Wednesday, February 14, 2018 3:52 PM
  • User206383436 posted

    I found that I have to set the "url" parameter in the AJAX call as follows:

    url: "http://localhost:port/api/SeccArtGen/"

    Where port is the port number where my project runs. This way everything works correctly.
    One disadvantage of specifying the "localhost:port" number is that I need to modify it when uploading the website to the production server.
    Is there a way of getting rid of "localhost:port"?

    Best regards.

    Thursday, February 15, 2018 12:15 AM
  • User283571144 posted

    Hi JORGEMAL,

    Where port is the port number where my project runs. This way everything works correctly.
    One disadvantage of specifying the "localhost:port" number is that I need to modify it when uploading the website to the production server.
    Is there a way of getting rid of "localhost:port"?

    According to your description, I suggest you could add javascript in the layout view to get the application base url.

    Then you could directly use the application base url in the ajax.

    More details about how to get the application base url, you could refer to below codes:

        <script type="text/javascript">
     
        window.applicationBaseUrl = @Html.Raw(HttpUtility.JavaScriptStringEncode(
            new Uri(
                       new Uri(this.Context.Request.Url.GetLeftPart(UriPartial.Authority)),
                       Url.Content("~/")
                   ).ToString(), true));
        alert(window.applicationBaseUrl + "asd.html");
        </script>

    Result:

    Best Regards,

    Brando

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, February 15, 2018 4:27 AM