Я использую безфайловую активацию, вот мой полный файл web.config на стороне сервера, который имеет две конечные точки:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework"
type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
requirePermission="false" />
</configSections>
<connectionStrings>
<add name="RedStripe"
connectionString="Data Source=S964;Initial Catalog=MyDatabase;Persist Security Info=True;User ID=sa;Password=***;MultipleActiveResultSets=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
<system.web>
<customErrors mode="Off"/>
</system.web>
<system.serviceModel>
<serviceHostingEnvironment>
<!-- where virtual .svc files are defined -->
<serviceActivations>
<add service="Company.Project.Business.Services.AccountClassService"
relativeAddress="Account/AccountClassService.svc"
factory="Company.Project.WebHost.CustomServiceHostFactory"/>
<add service="Company.Project.Business.Services.AccountService"
relativeAddress="Account/AccountService.svc"
factory="Company.Project.WebHost.CustomServiceHostFactory"/>
</serviceActivations>
</serviceHostingEnvironment>
</system.serviceModel>
</configuration>
Вот мой CustomServiceHostFactory:
public class CustomServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new CustomServiceHost(serviceType, baseAddresses);
}
}
А вот мой CustomServiceHost:
public class CustomServiceHost : ServiceHost
{
public CustomServiceHost(Type serviceType, Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
}
protected override void InitializeRuntime()
{
AddServiceDebugBehavior();
AddWcfMessageLoggingBehavior();
AddGlobalErrorHandlingBehavior();
AddServiceCredentialBehavior();
AddEndpoints();
ConfigureThrottling();
base.InitializeRuntime();
}
private void AddEndpoints()
{
var wsHttpBinding = WcfHelpers.ConfigureWsHttpBinding();
foreach (Uri address in BaseAddresses)
{
var endpoint = new ServiceEndpoint(
ContractDescription.GetContract(Description.ServiceType),
wsHttpBinding, new EndpointAddress(address));
AddServiceEndpoint(endpoint);
//adding mex
AddServiceMetadataBehavior();
AddServiceEndpoint(
ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexHttpBinding(),
address.AbsoluteUri + "/mex");
break;
}
}
private void AddGlobalErrorHandlingBehavior()
{
var errorHanlderBehavior = Description.Behaviors.Find<GlobalErrorBehaviorAttribute>();
if (errorHanlderBehavior == null)
{
Description.Behaviors.Add(new GlobalErrorBehaviorAttribute(typeof(GlobalErrorHandler)));
}
}
private void AddServiceCredentialBehavior()
{
var credentialBehavior = Description.Behaviors.Find<ServiceCredentials>();
if (credentialBehavior == null)
{
var customAuthenticationBehavior = new ServiceCredentials();
customAuthenticationBehavior.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
customAuthenticationBehavior.UserNameAuthentication.CustomUserNamePasswordValidator = new CustomUserNamePasswordValidator();
Description.Behaviors.Add(customAuthenticationBehavior);
}
}
private void AddServiceDebugBehavior()
{
var debugBehavior = Description.Behaviors.Find<ServiceDebugBehavior>();
if (debugBehavior == null)
{
Description.Behaviors.Add(
new ServiceDebugBehavior() {IncludeExceptionDetailInFaults = true});
}
else
{
if (!debugBehavior.IncludeExceptionDetailInFaults)
debugBehavior.IncludeExceptionDetailInFaults = true;
}
}
private void AddServiceMetadataBehavior()
{
var metadataBehavior = Description.Behaviors.Find<ServiceMetadataBehavior>();
if (metadataBehavior == null)
{
ServiceMetadataBehavior serviceMetadataBehavior = new ServiceMetadataBehavior();
serviceMetadataBehavior.HttpsGetEnabled = true;
Description.Behaviors.Add(serviceMetadataBehavior);
}
}
private void AddWcfMessageLoggingBehavior()
{
var messageInspectorBehavior = Description.Behaviors.Find<WcfMessageInspector>();
if (messageInspectorBehavior == null)
{
Description.Behaviors.Add(new WcfMessageInspector());
}
}
private void ConfigureThrottling()
{
var throttleBehavior = Description.Behaviors.Find<ServiceThrottlingBehavior>();
if (throttleBehavior != null) return;
throttleBehavior = new ServiceThrottlingBehavior
{
MaxConcurrentCalls = 100,
MaxConcurrentInstances = 100,
MaxConcurrentSessions = 100
};
Description.Behaviors.Add(throttleBehavior);
}
}
Наконец, вот WcfHelper, в котором определена привязка. Это находится в общем месте, поэтому я могу программно настроить привязку на стороне клиента, используя то же самое:
public class WcfHelpers
{
public static WSHttpBinding ConfigureWsHttpBinding()
{
return new WSHttpBinding
{
Name = "myWSHttpBinding",
OpenTimeout = new TimeSpan(0, 10, 0),
CloseTimeout = new TimeSpan(0, 10, 0),
SendTimeout = new TimeSpan(0, 10, 0),
MaxBufferPoolSize = 104857600,
MaxReceivedMessageSize = 104857600,
Namespace = Constants.RedStripeNamespace,
ReaderQuotas = new XmlDictionaryReaderQuotas()
{
MaxDepth = 104857600,
MaxStringContentLength = 104857600,
MaxArrayLength = 104857600,
MaxBytesPerRead = 104857600,
MaxNameTableCharCount = 104857600
},
Security =
{
Mode = SecurityMode.TransportWithMessageCredential,
Message = { ClientCredentialType = MessageCredentialType.UserName }
}
};
}
}
Когда я публикую этот проект WebHost и пытаюсь перейти к одному из двух адресов, например: https://myserver/Project/Account/AccountService.svc я получаю следующую ошибку:
Предоставленная схема URI «http» недействительна; ожидаемый «https». Имя параметра: context.ListenUriBaseAddress
Я заметил, что в методе CustomServiceHost AddEndpoints() при переборе BaseAddresses, если я жестко прописываю там адрес, например: https://myserver/Project/Account/AccountService.svc Затем я могу успешно перейти к нему. Как строятся BaseAddresses при использовании безфайловой активации и относительной адресации? Где я могу указать, что они используют https (там, где сейчас они используют http)?
Заранее спасибо.
Редактировать 1: Это решит проблему, но похоже на полный взлом. Где мне указать https с помощью безфайловой активации, чтобы относительный адрес строился с https?
var endpoint = new ServiceEndpoint(ContractDescription.GetContract(Description.ServiceType),
wsHttpBinding, new EndpointAddress(address.OriginalString.Replace("http:", "https:")));
Изменить 2: кажется, я начинаю понимать, что здесь происходит. Спасибо @Andreas K за то, что указали мне правильное направление. Если я зайду в IIS и посмотрю привязки для сайта, их будет несколько, как показано на изображении:
Я поместил некоторый код для записи в базу данных внутри моего метода AddEndpoints() при переборе BaseAddresses. Когда я пытаюсь использовать браузер для доступа к службе, например: https://my.server.local/Project/Account/AccountService.svc, в базе данных создаются ДВЕ записи. http://my.server.local/Project/Account/AccountService.svc https://my.server.local/Project/Account/AccountService.svc а>
Таким образом, кажется, что IIS SITE BINDING подхватывается. Однако теперь я не уверен, почему в базе данных нет больше записей для BaseAddresses. Где находятся net.pipe, net.tcp и т. д.?
app.config
на стороне сервера? - person tchrikch   schedule 04.05.2015