Создание службы wcf в IIS в коде

У меня есть служба Saas, которая имеет несколько групп сайтов (каждая группа, принадлежащая разному клиенту), запущенных на одном сайте IIS с другим iis-связыванием / именем хоста, так что это план.

Проблема в том, что у меня есть службы WCF для сайтов, и они работают на.net3.5. У меня не может быть нескольких базовых адресов, использующих один и тот же протокол. Я мог бы обновить до.net4 и включить это, но я бы предпочел запускать только те службы, которые мне нужны, в настоящее время по одному сайту на группу, а также не нужно продвигать обновление.

Я пытался сделать это путем создания служб в коде (две попытки ниже). Это дает мне полный контроль над тем, когда и где создаются сервисы (а также за счет удаления фрагмента почти никогда не меняющегося конфига wcf из web.config).

Оригинальная попытка:

using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Web;

[ServiceContract(Namespace = "WcfInIis")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Tiny
{
    [OperationContract]
    public bool IsTiny()
    {
        return true;
    }
}

public class Global : System.Web.HttpApplication
{
    protected void Application_Start(object sender, EventArgs e)
    {
        Uri requestUri = HttpContext.Current.Request.Url;
        //some logic to decide if this context is allowed to run the wcf service requested
        ServiceHost host = new ServiceHost(typeof(Tiny), new Uri(requestUri.OriginalString.Replace(requestUri.LocalPath, string.Empty)));
        WSHttpBinding binding = new WSHttpBinding(SecurityMode.None);
        host.AddServiceEndpoint(typeof(Tiny), binding, "_service/tiny");
        host.Open();
    }
}

Проблема с кодом в том, что когда он запускается, я получаю AddressAccessDeniedException: HTTP could not register URL http://+:56134/. Your process does not have access rights to this namespace (see http://go.microsoft.com/fwlink/?LinkId=70353 for details).], Очевидно, что это работает в Кассини, но я получаю то же сообщение при запуске в IIS.

Когда я перехожу по ссылке и выполняю команду, она предлагает netsh http add urlacl url=http://+:56134/ user=domain\username Я получил пустой экран, так как ни один из asp.net не выполняется, и служба недоступна по указанному URL.

В итоге проблемы:

  1. Необходимо запустить команду netsh (это изменение конфигурации, которое мне не нужно записывать и вносить для каждого сайта, на котором запущены службы wcf)
  2. ломает страницы asp.net

Пересмотренная попытка

Используя предложение @Nick Nieslanik, я построил следующее

 используя Систему;
using System.ServiceModel;
using System.ServiceModel.Activation;
использование System.Web;
использование System.Web.Routing;

[ServiceContract (Namespace = "WcfInIis")]
[AspNetCompatibilityRequirements (RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
открытый класс Tiny
{
    [OperationContract]
    публичный bool IsTiny()
    {
        вернуть истину;
    }
}

открытый класс ffServiceHandler: IRouteHandler, IHttpHandler
{
    #region IRouteHandler Участники

    public System.Web.IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        верни это;
    }

    #endregion

    #region IHttpHandler Участники

    public bool IsReusable
    {
        get {return false; }
    }

    public void ProcessRequest (контекст HttpContext)
    {
        Uri requestUri = context.Request.Url;
        // некоторая логика, чтобы решить, разрешено ли этому контексту запускать запрошенный сервис wcf
        ServiceHost host = new ServiceHost(typeof(Tiny), новый Uri(requestUri.OriginalString.Replace(requestUri.LocalPath, string.Empty)));
        WSHttpBinding binding = новый WSHttpBinding(SecurityMode.None);
        host.AddServiceEndpoint(typeof(Tiny), привязка, "_services/tiny");
        host.Open(); // генерирует AddressAlreadyInUseException
    }

    #endregion
}

открытый класс Global: System.Web.HttpApplication
{
    защищенный void Application_Start(отправитель объекта, EventArgs e)
    {
        RouteTable.Routes.Add(новый маршрут
        (
                "_Services / крошечное",
                новый ffServiceHandler()));
    }
} 

Эта пересмотренная попытка имеет проблемы:

  1. Еще нужно запустить команду netsh (это изменение конфигурации, которое мне не нужно записывать и вносить для каждого сайта, на котором запущены службы wcf)
  2. Теперь я получаю [AddressAlreadyInUseException: HTTP could not register URL http://+:56134/ because TCP port 56134 is being used by another application.] когда я пытаюсь получить доступ к сайту. Это вызвано тем, что служба пытается запустить службу wcf на том же порту, на котором работает сайт.

Резюме

Может ли кто-нибудь помочь мне получить один из этих работ так:

  1. служба wcf запускается успешно
  2. сервис работает только по своему полному URL (не только пути)
  3. не мешает страницам asp.net
  4. Не требует изменений конфигурации на сервере (т.е. не запускается команда netsh)

Я думаю, что альтернативным решением может быть создание динамического файла.svc, как описано здесь. Я попробую и опубликую свои результаты. Кажется, что именно так asp.net обрабатывает файлы.svc, когда они запрашиваются, потому что как еще можно избежать исключения AddressAlreadyInUseException?

Спасибо

Кит

1 ответ

Один из способов сделать это - использовать ASP.NET UrlRouting и реализовать объект IRouteHandler, который будет ускорять хосты службы WCF...

http://msdn.microsoft.com/en-us/library/system.web.routing.iroutehandler.gethttphandler.aspx

http://msdn.microsoft.com/en-us/library/cc668201.aspx

Я делал это в прошлом при настройке WCF Data Services, и я не понимаю, почему это не может работать здесь.

Другие вопросы по тегам