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

#wcf #iis-7

#wcf #iis-7

Вопрос:

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

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

Я пытался сделать это, создав службы в code (две попытки ниже). Это дает мне полный контроль над тем, когда и где создаются службы (а также удаление фрагмента почти никогда не меняющейся конфигурации 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).] . Очевидно, что это выполняется в Cassini, но я получаю то же сообщение при запуске в IIS.

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

В итоге проблемы заключаются в:

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

Исправленная попытка

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

использование System; 
использование System.ServiceModel;
использование System.ServiceModel.Активация;
использование System.Web; 
использование System.Web.Routing;

[ServiceContract(пространство имен = "WcfInIis")]
[Требования к совместимости AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Разрешено)]
общедоступный класс Tiny
{
 [OperationContract]
 общедоступный bool IsTiny()
 { 
 возвращает true;
 }
}

открытый класс ffServiceHandler: IRouteHandler, IHttpHandler
{
 #региональные участники IRouteHandler

 общедоступная System.Web.IHttpHandler GetHttpHandler(RequestContext Запрос context)
 {
 верните это;
 }

 #конечный регион

 #region Члены IHttpHandler

 общедоступный bool является недопустимым
 {
 получаем { return false; }
 }

 общедоступный недействительный запрос процесса (контекст HttpContext)
 {
 Uri RequestURI = context.Request.Url;
 //некоторая логика, позволяющая решить, разрешено ли в этом контексте запускать запрошенную службу wcf
 ServiceHost host = новый ServiceHost(typeof(крошечный), новый Uri (RequestURI.OriginalString.Заменить(RequestURI.localPath, строка.Пусто)));
 Привязка wsHttpBinding = новая привязка wsHttpBinding (SecurityMode.None);
 хост.AddServiceEndpoint(typeof(Tiny), привязка, "_services/tiny");
 хост.Open(); // выдает исключение AddressAlreadyInUseException
 }

 #конечный регион
}

глобальный общедоступный класс: System.Web.HttpApplication
{
 защищенное недействительное Application_Start (отправитель объекта, EventArgs e)
 {
 Маршрутизируемый.Маршруты.Добавить (новый маршрут
 (
 "_services/tiny", 
 новый 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 (а не только с path)
  3. не мешает asp.net страницы
  4. Не требует изменения конфигурации сервера (т. Е. не выполняется команда netsh)

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

Спасибо

Кит

Ответ №1:

Одним из способов добиться этого было бы использовать ASP.NET Маршрутизация URL и реализация объекта 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, и я не понимаю, почему это не может работать и здесь.

Комментарии:

1. @KeithK Нет проблем, извините, я не предоставил более подробной информации, я выбегал за дверь. Если у меня сегодня будет немного времени, я попытаюсь подробнее изложить ответ.

2. Только что обновил свой вопрос попыткой использования маршрутизации, но возникла новая проблема с исключением AddressAlreadyInUseException.

3. @KeithK У меня нет времени рассматривать это сегодня, но я займусь этим как можно скорее.