Wywołanie kontrolera web api z poziomu javascript

0

Witam, walczę od dwóch dni z pewnym przypadkiem. Mam aplikację webową ASP.NET :

Wywołuję w widoku z poziomu javascriptu ajax'owo controller web api, aby otrzymać dane. Dostaję error 500 internal server error - nie znajduje mi ścieżki do kontrolera. Ponizej kod:

WIDOK

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8" />

</head>
<body>

<div id="data"></div>

    <button onclick="getName()">Click me</button>

<script type="text/javascript">

   function getName() {
       var userFullName;
       $.ajax({
           method: "GET",
           url: "/api/user/getFullName",
           contentType: "application/json; charset=utf-8",
           success: function (result) {
               userFullName = result;
           }
       });
            
        };

     

   
    </script>

</body>
</html>
 

API KONTROLER:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using ChatSignalR.Services;
using System.Web;
using Microsoft.AspNet.Identity;
using System.Security.Claims;
using System.Web;
using System.Web.Http.Results;

namespace ChatSignalR.Controllers.Api
{
    [Authorize]
    public class UserController : ApiController
    {
        private readonly IUserService _userService;

        public UserController(IUserService userService)
        {
            _userService = userService;        
        }

        [Route("api/user/getFullName")]
        [HttpGet]
        public IHttpActionResult GetUserFullName()
        {
            string fullName = _userService.GetCurrentUserFullName();
            return Ok(fullName);
        }

    

    }
}

W pliku WebApiConfig.cs:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;

namespace ChatSignalR
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
         
            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
}

Global.asax:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace ChatSignalR
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);        
        }
    }
}

Nie mogę tego rozgryźć za cholerę

0

500 internal server error - nie znajduje mi ścieżki do kontrolera.

Na pewno chodzi o ścieżkę?
Jak nie znajduje ścieżki to raczej powinno zwrócić 404, a nie 500. Sprawdzałeś czy w _userService.GetCurrentUserFullName() nie leci jakiś wyjątek?

0

W ogóle nie dochodzi do wywołania metody GetUserFullName(), bo ustawiam tam break-pointa w VS i nie zatrzymuje się.
Wygląda na to jakby nie widział tej ścieżki Route[] podanej nad metodą.

0

http://localhost:55525/ - to mam w polu Project -> properties -> Web -> Url (odpowiedź na komentarz z 1szego posta, wcześniej nie zauważyłem)

0

skoro błąd 500 to najlepiej postaw brakepoint w tym api/user/getFullName i zobacz jaki wyjątek leci :)

0

Pisałem 2 posty powyżej, że postawiłem breakpointa, ale w ogóle nie dochodzi do wywołania tej akcji.

0

Po co Ci w ajax contentType: "application/json; charset=utf-8",?? Wysyłasz jsony GETem? Nie widać, żebyś cokolwiek wysyłał.

0
  1. Jeśli chodzi o contentType: "application/json; charset=utf-8" - mam analogiczny przykład w drugiej aplikacji, gdzie to działa, tutaj z pewnością nie leży problem.. problem jest taki, jakby z poziomu wywołania tego ajax'owego url: .. jest niewidoczny
  2. userservice jest wstrzykiwany do kontrolera, to jest zrobione poprawnie
0

W definicji routingu nie masz {action}.

0

To też nie tego wina, raz jeszcze kod:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;

namespace ChatSignalR
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
         
            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/{id}",             // czy dam tutaj z {action}, czy pominę {action} rezultat ten sam
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
} 
 [Route("api/user/getFullName")]
        [HttpGet]
        public IHttpActionResult GetUserFullName()
        {
            string fullName = _userService.GetCurrentUserFullName();
            return Ok(fullName);
        }
<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8" />

</head>
<body>

<div id="data"></div>

    <button onclick="getName()">Click me</button>

<script type="text/javascript">

   function getName() {
       var userFullName;
       $.ajax({
           method: "GET",
           url: "/api/user/getFullName",
           contentType: "application/json; charset=utf-8",
           success: function (result) {
               userFullName = result;
           }
       });
            
        };

     
    </script>
 

W załączniku dodałem screena z błędem z developer tool'a F12

0

Co jak przez przeglądarkę wejdziesz pod ten link?

Jak dla mnie tam gdzieś leci Ci exception.

0

Najpierw poszedł error, że nie ma bezparametrycznego konstruktora zdefiniowanego dla UserController (dodałem go, chociaz nie wiem po co on jest potrzebny). Teraz dostaję coś takiego, po wpisaniu do przeglądarki :
http://localhost:55525/api/user/getFullName

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
Object reference not set to an instance of an object.
</ExceptionMessage>
<ExceptionType>System.NullReferenceException</ExceptionType>
<StackTrace>
at ChatSignalR.Controllers.Api.UserController.GetUserFullName() in C:\Users\Michał\documents\visual studio 2015\Projects\ChatSignalR\ChatSignalR\Controllers\Api\UserController.cs:line 34 at lambda_method(Closure , Object , Object[] ) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()
</StackTrace>
</Error>
0

No tak, a jakiego kontenera IoC używasz?
Bo ASP.NET WebApi domyślnie umie tworzyć tylko kontrolery z bezparametrowymi konstrktorami.
Czyli problem z nullem i exception leci.

0

używam UnityConfig

1

No to w takim razie nie ustawiłeś, żeby WebApi z niego korzystało.
Inaczej nie byłoby błędu o konieczności posiadania bezparametrowego konstruktora w kontrolerze.

0

Uff.. problem rozwiązany.. okazało się, że brakowało paczki Unity.WebApi oraz w pliku UnityConfig.cs :

  public class UnityConfig
    {
        #region Unity Container
        private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
        {
            var container = new UnityContainer();
            RegisterTypes(container);
           ** System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);**
            return container;
        });
.....

linii zaznaczonej pogrubioną linią, to dla potomnych. Dzięki

1 użytkowników online, w tym zalogowanych: 0, gości: 1