#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.
В итоге проблемы заключаются в:
- Необходимо запустить команду netsh (это изменение конфигурации, которое я бы предпочел не записывать и не вносить для каждого сайта, на котором запущены службы wcf)
- нарушает 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()
));
}
}
Эта пересмотренная попытка имеет проблемы:
- Все еще необходимо запустить команду netsh (это изменение конфигурации, которое я бы предпочел не записывать и не вносить для каждого сайта, на котором запущены службы wcf)
- Теперь я получаю
[AddressAlreadyInUseException: HTTP could not register URL http:// :56134/ because TCP port 56134 is being used by another application.]
, когда пытаюсь получить доступ к сайту. Это вызвано тем, что служба пытается запустить службу wcf на том же порту, на котором запущен сайт.
Краткие сведения
Кто-нибудь может помочь мне заставить один из них работать так:
- служба wcf успешно запускается
- служба работает только со своим полным URL (а не только с path)
- не мешает asp.net страницы
- Не требует изменения конфигурации сервера (т. Е. не выполняется команда 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 У меня нет времени рассматривать это сегодня, но я займусь этим как можно скорее.