Проблема с подключением к веб-службе WCF

Позвольте мне начать с того, что я впервые работаю с веб-сервисами WCF, и последние 3 дня я боролся с ошибкой. На эти вопросы много раз отвечали в Stackoverflow, однако я пробовал большинство решений и пока не добился успеха, поэтому мне нужна помощь в определении правильного пути.

Теперь немного предыстории. Я создаю проект ASP.Net MVC 5, мне нужно подключиться к веб-службам WCF, предоставляемым Epicor (решение ERP). Мой проект, ERP и ее веб-сервисы размещены во внутреннем экземпляре IIS. Службы предоставляются с использованием протоколов BasicHTTP и NetTCP. Пул приложений, в котором размещены веб-служба и ERP, использует идентификатор. Один из веб-сервисов называется Company.svc и отображается как:

<wsdl:service name="CompanySvcFacade">
    <wsdl:port name="BasicHttpBinding_CompanySvcContract" binding="tns:BasicHttpBinding_CompanySvcContract">
        <soap:address location="http://pilotserver/ERP100700/Ice/BO/Company.svc"/>
    </wsdl:port>
    <wsdl:port name="CustomBinding_CompanySvcContract" binding="tns:CustomBinding_CompanySvcContract">
        <soap12:address location="net.tcp://pilotserver/ERP100700/Ice/BO/Company.svc"/>
        <wsa10:EndpointReference>
            <wsa10:Address>net.tcp://pilotserver/ERP100700/Ice/BO/Company.svc</wsa10:Address>
            <Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity">
                <Upn>pilotserver\Administrator</Upn>
            </Identity>
        </wsa10:EndpointReference>
    </wsdl:port>
</wsdl:service>

В моем проекте мой web.config имеет следующее:

<system.serviceModel>
<bindings>
  <basicHttpBinding>
    <binding name="BasicHttpBinding_CompanySvcContract" />
  </basicHttpBinding>
  <customBinding>
    <binding name="CustomBinding_CompanySvcContract">
      <security defaultAlgorithmSuite="Default" authenticationMode="UserNameOverTransport"
        requireDerivedKeys="true" includeTimestamp="true" messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
        <localClientSettings detectReplays="false" />
        <localServiceSettings detectReplays="false" />
      </security>
      <textMessageEncoding />
      <windowsStreamSecurity />
      <tcpTransport />
    </binding>
  </customBinding>
</bindings>
<client>
  <endpoint address="http://pilotserver/ERP100700/Ice/BO/Company.svc"
    binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_CompanySvcContract"
    contract="CompanyService.CompanySvcContract" name="BasicHttpBinding_CompanySvcContract" />
  <endpoint address="net.tcp://pilotserver/ERP100700/Ice/BO/Company.svc"
    binding="customBinding" bindingConfiguration="CustomBinding_CompanySvcContract"
    contract="CompanyService.CompanySvcContract" name="CustomBinding_CompanySvcContract">
    <identity>
      <userPrincipalName value="pilotserver\Administrator" />
    </identity>
  </endpoint>
</client>

And I'm trying to consume the web service in the client using the following code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using EpicorTestApp.CompanyService;
using NLog;
namespace EpicorTestApp.Controllers
{
    public class HomeController : Controller
    {
        CompanySvcContractClient CompanyService = new CompanySvcContractClient("CustomBinding_CompanySvcContract");
        //CompanySvcContractClient CompanyService = new CompanySvcContractClient("BasicHttpBinding_CompanySvcContract");
        private Logger logger = LogManager.GetCurrentClassLogger();
        public ActionResult Index()
        {
            ViewBag.Message = "Welcome to ASP.NET MVC!";
            bool morePages = false;

            CompanyService.ClientCredentials.UserName.UserName = "Administrator";
            CompanyService.ClientCredentials.UserName.UserName = "myPassword";
            CompanyListTableset companyList = CompanyService.GetList("", 0, 0, out morePages);
            CompanyListTable companies = companyList.CompanyList;
            foreach (CompanyListRow companyListRow in companies)
            {
                logger.Info("Company: " + companyListRow.Company);
            }           
            return View();
        }
    }
}

Для привязки клиента я пробовал и BasicHttp, и NetTCP (в качестве CustomBinding), что приводило к некоторым ошибкам. Когда я создаю привязку BasicHttp, я использую следующую конфигурацию ссылки на службу:

BasicHttpBinding

и после запуска этой конфигурации я получаю сообщение об ошибке «Доступ запрещен. Сведения об исключении: System.ServiceModel.Security.SecurityAccessDeniedException: Доступ запрещен».

Ошибка BasicHttp

А для привязки nettcp, когда я пытаюсь создать ссылку на службу, я получаю сообщение об ошибке «Префикс URI не распознан. Метаданные содержат ссылку, которую невозможно разрешить: net.tcp://localhost/ERP100700/Ice/ BO/Company.svc». Я пытался использовать в URL-адресе как localhost, так и pilotserver.

Ошибка NetTcp

Я пытался запустить приложение как в режиме отладки (ISS-Express), так и опубликовать его в IIS, но результат тот же. Что я делаю не так и как решить эту проблему?


person SJaka    schedule 10.07.2016    source источник
comment
Может быть сложно сгенерировать клиентский код net.tcp и подобные контракты. Поскольку он находится на вашем локальном ПК, попробуйте скопировать контракт интерфейса и зависимые от него контракты данных в клиентское приложение и использовать ChannelFactory для создания прокси-сервера net.tcp. Что касается BasicHttp, вам нужно будет перехватить этот запрос и посмотреть, какая информация передается службе, которая говорит, что вы не авторизованы. Для этого вы можете использовать Fiddler, WCF Tracing или даже (я настоятельно рекомендую) Wireshark.   -  person Dandré    schedule 10.07.2016
comment
Некоторые из вещей, которые я упомянул, предполагают, что вы знаете основы, и я не буду их объяснять, есть много руководств и документации Google, которые будут.   -  person Dandré    schedule 10.07.2016
comment
К вашему сведению, вы не можете добавить ссылку на службу, используя протокол net.tcp, вы делаете это через http. Пока конфигурация службы правильно отображает конечную точку net.tcp, вы сможете использовать ее на основе WSDL, извлеченного из файла http. Нет необходимости добавлять ссылку второй раз для net.tcp.   -  person R. Richards    schedule 10.07.2016


Ответы (2)


В HomeController казалось бы, что это

CompanyService.ClientCredentials.UserName.UserName = "Administrator";
CompanyService.ClientCredentials.UserName.UserName = "myPassword";

Должно быть что-то вроде этого

CompanyService.ClientCredentials.UserName.UserName = "Administrator";
CompanyService.ClientCredentials.UserName.Password = "myPassword

Вы дважды передаете имя пользователя в коде, когда представляете его.

person R. Richards    schedule 10.07.2016
comment
Я не могу поверить в эту опечатку. Спасибо, что заметили это. Однако ошибка все та же. Однако еще раз спасибо за это. - person SJaka; 10.07.2016
comment
Вы по-прежнему получаете сообщение об отказе в доступе при использовании клиента HTTP (BasicHttpBinding_CompanySvcContract) после правильной отправки пароля? - person R. Richards; 10.07.2016
comment
Да, та же ошибка. Вероятно, вопрос, который следует задать на этом этапе, заключается в том, как правильно установить учетные данные в веб-конфигурации и/или клиентском коде? Я пробовал комбинации "CompanyService.ClientCredentials.UserName.UserName/Password" и "CompanyService.ChannelFactory.Credentials.UserName.UserName/Password". Кроме того, в средстве просмотра событий Windows я заметил, что получаю сообщение об ошибке «Ошибка авторизации службы» с пустым идентификатором клиента «ClientIdentity:». - person SJaka; 10.07.2016
comment
Еще одна вещь, которую следует учитывать: Thread.CurrentPrincipal. Стоит поискать. Создайте GenericPrincipal, заполните его, добавьте к этому свойству. (??) - person R. Richards; 10.07.2016

Причина, по которой я получал все эти ошибки, заключалась в том, что в Web.config для веб-служб Epicor (внутри IIS) схема https для BasicHTTP была отключена/закомментирована. Мне пришлось добавить следующее, чтобы мое приложение заработало.

  <remove scheme="https" />
  <add scheme="https" binding="basicHttpBinding" bindingConfiguration="BasicHttp"/> 

Это поведение по умолчанию в Epicor.

person SJaka    schedule 13.07.2016