Array
(
)

Erro ao tentar consumir serviço WebAPI

Pjava
   - 07 jul 2016

desde hoje pela manhã tento pegar um JSON que um WebAPI disponibiliza. Primeiramente tentei com insira o código aquiAngularJS e não estava evoluindo, então fui para o clássico Jquery/Ajax e mesmo assim não obtive êxito. No meu WebAPI eu, via NuGet, instalei o CORS, pois a razão disso é fazer funcionar com Cross-Domain. Fiz um exemplo simples, usando CROSS-DOMAIN e funcionou bem. O que passa é que pelo projeto que tenho aqui na empresa é que não está funcionando, ou seja, não consigo pegar o JSON no meu client. O serviço está funcionando bem. Bem, vou postar os códigos e caso a pergunta ainda não estar clara, favor, sintam-se a vontade para questionar/perguntar. Abaixo está o JSON capturado no Browser. Observe, que pelo ajax, eu não tenho um data(foi o que eu entendi), mas sim um data.items.
#Código

{
  "totalRecords": 40,
  "pagination": {
    "pageIndex": 1,
    "pageSize": 40,
    "lastPage": 1
  },
  "sort": {
    "fields": "Nome",
    "directions": "ASC"
  },
  "items": [
    {
      "id": 49,
      "nome": "Assinatura PME",
      "tipoContato": {
        "codigo": "T",
        "descricao": "Texto"
      },
      "dataUltimaAtualizacao": "2015-06-11T22:13:52",
      "loginUltimaAtualizacao": "Teste"
    },
    {
      "id": 14,
      "nome": "Capa para Baixo - Cartas",
      "tipoContato": {
        "codigo": "T",
        "descricao": "Texto"
      },
      "dataUltimaAtualizacao": null,
      "loginUltimaAtualizacao": null
    }
  ]
}

Esse é o código do serviço(ApiController):
#Código
using System.Web.Http.Cors;
namespace X.EstruturaOrganizacional.Api.Controllers
{
    [RoutePrefix("api/estruturaOrganizacional")]
    [EnableCors(origins: "http://localhost:64628/", headers: "*", methods: "*")]
    public class TipoContatoOperadoraController : ApiXController
    {
        private readonly ITipoContatoOperadoraService service;

        public TipoContatoOperadoraController()
        {
            DependencyResolver.Resolve(Container);

            service = Container.Resolve<ITipoContatoOperadoraService>();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && service != null)
            {
                service.Dispose();
            }

            base.Dispose(disposing);
        }

        [HttpGet]
        [Route("tiposContatoOperadora")]
        //[CleanOutCompression]
        [CacheOutput(ClientTimeSpan = 10, ServerTimeSpan = 10)]
        public Task<HttpResponseMessage> ObterTiposContatoOperadora(
            string sortFields = "Nome",
            string sortDirections = "ASC",
            int? pageSize = null,
            int pageIndex = 1)
        {
            IEnumerable<TipoContatoOperadora> lista = service.Listar(
                sortFields,
                sortDirections,
                pageSize,
                pageIndex,
                out recordCount,
                out sorts);

            return CreateResponseForList(lista.ToListModel(), pageIndex, pageSize);
        }

        [HttpGet]
        [Route("tiposContatoOperadora/{id}")]
        //[CleanOutCompression]
        [CacheOutput(ClientTimeSpan = 10, ServerTimeSpan = 10)]
        public Task<HttpResponseMessage> ObterTipoContatoOperadoraPorId(
            byte id)
        {
            TipoContatoOperadora item = service.ConsultarPorCodigo(id);

            return CreateResponseForItem(item.ToModel());
        }
    }
}

E aqui está o meu client(Angular)
#Código
@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Tipo Contato Operadora</h2>

<div data-ng-controller="TipoContatoOperadoraController">
    <div class="panel panel-default">
        <div class="panel-heading">Lista de Tipo de Contato das Operadoras</div>
        <div class="panel-body">
            <div class="row">
                <div class="col-md-12">
                        <strong>{{erro}}</strong>
                    </div>
            </div>
            <div class="row">
                <div class="col-md-12">
                    <div class="table-responsive">
                            <table class="table table-bordered table-hover">
                                <tr>
                                    <th>Cod. Tipo Contato</th>
                                    <th>Nome Tipo Contato</th>
                                    <th>Ind. Tipo Contato</th>
                                    <th>Data Atualização</th>
                                    <th>Cod. Usuário</th>
                                </tr>
                                <tr data-ng-repeat="lista in listaTipoContatoOperadora">
                                    <td>{{ lista.id }}</td>
                                    <td>{{ lista.nome }}</td>
                                    <td>{{ lista.tipoContato }}</td>
                                    <td>{{ lista.dataUltimaAtualizacao }}</td>
                                    <td>{{ lista.loginUltimaAtualizacao }}</td>
                                </tr>
                            </table>
                        </div>
                    <input type="button" value="Tente Isso" onclick="sendRequest()" />
                    <span id='value1'>(Result)</span>
                </div>
            </div>
        </div>
    </div>
</div>

Minha controller Angular:
#Código
var app = angular.module('app', []);

//app.controller('TipoContatoOperadoraController', ['$scope', '$http', TipoContatoOperadoraController]);

app.controller('TipoContatoOperadoraController', function ($scope, $http) {

    $http.get('http://localhost:7215/api/estruturaOrganizacional/tiposContatoOperadora')
    .success(function (data) {

        $scope.listaTipoContatoOperadora = data.items;
    })
    .error(function () {
        $scope.erro = 'Erro: Não foi possível carregar a lista do tipo de contato das operadoras.';
    });
})

Numa tentativa de não utilizar o Angular, comentei toda chamada ao Angular e fiz esse Javascript, que coloquei abaixo na minha Index:
#Código
@section scripts {
    <script>
    // TODO: Replace with the URL of your WebService app
        var serviceUrl = 'http://localhost:7215/api/estruturaOrganizacional/tiposContatoOperadora';

    function sendRequest() {
        var method = $('#method').val();

        $.ajax({
            type: method,
            url: serviceUrl
        }).done(function (data) {
            $('#value1').text(data);
        }).error(function (jqXHR, textStatus, errorThrown) {
            $('#value1').text(jqXHR.responseText || textStatus);
        });
    }
    </script>
}

Esse é o erro que dá no momento em eu tento consumir o serviço:

Citação:
XMLHttpRequest cannot load http://localhost:7215/api/estruturaOrganizacional/tiposContatoOperadora. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:64628' is therefore not allowed access. The response had HTTP status code 500.

O button Tente Isso e o span, utilizei com o javascript puro para testes, sem a table do Angular.
O AngularJS está funcionando, pois o Controller do AngularJS exibe a mensagem de erro cna página que vem do Serviço, está sendo exibida. O problema mesmo está na serialização(JSON), ou seja, não consigo pegar o JSON do serviço(function(data)).

Pjava
   - 07 jul 2016

Dentro da minha controller WebApi, eu tenho esse método:

[HttpGet]
[Route("tiposContatoOperadora")]
//[CleanOutCompression]
[CacheOutput(ClientTimeSpan = 10, ServerTimeSpan = 10)]
public Task<HttpResponseMessage> ObterTiposContatoOperadora(
string sortFields = "Nome",
string sortDirections = "ASC",
int? pageSize = null,
int pageIndex = 1)
{
IEnumerable<TipoContatoOperadora> lista = service.Listar(
sortFields,
sortDirections,
pageSize,
pageIndex,
out recordCount,
out sorts);

return CreateResponseForList(lista.ToListModel(), pageIndex, pageSize);
}
Será que nesse método é que eu tenho que configurar o Header para impedir o erro?

José Ferreira
   - 21 jul 2016

Acho que você deveria primeiro, testar sem utilizar o angularJS, tente simular a solicitação Get ou Post utilizando Postman, para você ter certeza que está tudo configurado certinho pro lado Back-end.