如何在自托管环境中注入对用作 RESTFul 服务的 WCF 服务的依赖
How to inject dependency on WCF service used as RESTFul service on selfhost enviroment
我需要一些示例来说明如何在自托管环境中使用 WCF 技术并使用 DI 容器(可能是 SimpleInjector)实现 RESTfull 服务。
在 https://simpleinjector.readthedocs.io/en/latest/wcfintegration.html 我找到了如何集成自定义工厂,但它是为 ServiceHost 制作的,但这不适合使用 WebServiceHost 的 RESTFull 服务?
我尝试将服务主机配置为与 webHttpBinding 兼容,但没有任何反应,我收到此类错误:
<Fault
xmlns="http://schemas.microsoft.com/ws/2005/05/envelope/none">
<Code>
<Value>Sender</Value>
<Subcode>
<Value
xmlns:a="http://schemas.microsoft.com/ws/2005/05/addressing/none">a:DestinationUnreachable
</Value>
</Subcode>
</Code>
<Reason>
<Text xml:lang="it-IT">Impossibile elaborare nel destinatario il messaggio con To 'http://localhost:8733/3AdispPushBatchService/pushpost' a causa di una mancata corrispondenza AddressFilter in EndpointDispatcher. Controllare la corrispondenza di EndpointAddresses del mittente e del destinatario.</Text>
</Reason>
</Fault>
是否有另一个集成包可用于 WebServiceHost?
这是我做的例子
AAADispPushBatchService.cs
using System;
using System.Configuration;
using System.IO;
using System.ServiceModel.Activation;
using System.Text;
using Newtonsoft.Json;
namespace AAARestService
{
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class AAADispPushBatchService : IAaaDispPushBatchService
{
public string GetBatchJson(Stream jsonFileContent)
{
try
{
var sr = new StreamReader(jsonFileContent, Encoding.UTF8);
var str = sr.ReadToEnd();
if (String.IsNullOrWhiteSpace(str))
throw new ArgumentException("No data inside body request");
var definition = new { BatchName = "" };
var json = JsonConvert.DeserializeAnonymousType(str, definition);
if (json == null)
throw new ArgumentException("No valid json inside");
if (String.IsNullOrWhiteSpace(json.BatchName))
throw new ArgumentException("BatchName not present");
var currentDir = ConfigurationManager.AppSettings["BatchPath"];
Directory.CreateDirectory(currentDir);
var filepath = Path.Combine(currentDir, json.BatchName+".json");
File.WriteAllText(filepath, str);
return $"Saved in {filepath}";
}
catch (Exception e)
{
return e.Message;
}
}
}
}
IAaaDispPushBatchService.cs
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Web;
namespace AAARestService
{
[ServiceContract(Name = "AAADispPushBatchService")]
public interface IAaaDispPushBatchService
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "pushpost", BodyStyle = WebMessageBodyStyle.Bare,ResponseFormat = WebMessageFormat.Json)]
string GetBatchJson(Stream jsonFileContent);
}
}
编辑!!!!!!
顺便说一句,我尝试在此处添加 simpleinjector,这是基于我在博客中找到的示例
Bootstrapper.cs
using System.Reflection;
using SimpleInjector;
namespace AAARestService
{
public static class BootStrapper
{
public static readonly Container Container;
static BootStrapper()
{
Container container = new Container();
container.Register<IMyDateTimeService,MyDAteTimeService>();
container.RegisterWcfServices(Assembly.GetExecutingAssembly());
Container = container;
}
}
}
MyWebServiceHostFactory.cs
public class MyWebServiceHostFactory : SimpleInjectorServiceHostFactory
{
public ServiceHost GetWebServiceEndpoint(Type serviceType,Uri baseAddress)
{
Uri[] addresses=new Uri[]{baseAddress};
var service = CreateServiceHost(serviceType, addresses);
ServiceEndpoint sep = service.AddServiceEndpoint(typeof(IAaaDispPushBatchService), new WebHttpBinding(), baseAddress);
sep.EndpointBehaviors.Add(new WebHttpBehavior());
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
service.Description.Behaviors.Add(smb);
return service;
}
protected override ServiceHost CreateServiceHost(Type serviceType,
Uri[] baseAddresses)
{
var host = new SimpleInjectorServiceHost(
BootStrapper.Container,
serviceType,
baseAddresses);
return host;
}
}
主要
static void Main(string[] args)
{
try
{
Uri httpUrl = new Uri("http://localhost:8733/3AdispPushBatchService");
Uri httpUrl1 = new Uri("http://localhost:8734/3AdispPushBatchService");
//ServiceHost selfhost = new ServiceHost(typeof(AAADispPushBatchService), httpUrl);
//ServiceEndpoint sep =selfhost.AddServiceEndpoint(typeof(IAaaDispPushBatchService),new WebHttpBinding(), httpUrl);
//sep.EndpointBehaviors.Add(new WebHttpBehavior());
//ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
//smb.HttpGetEnabled = true;
//selfhost.Description.Behaviors.Add(smb);
MyWebServiceHostFactory factory = new MyWebServiceHostFactory();
var selfhost=factory.GetWebServiceEndpoint(typeof(AAADispPushBatchService), httpUrl);
selfhost.Open();
//WebServiceHost webHost = new WebServiceHost(typeof(AAADispPushBatchService),httpUrl1);
//webHost.Open();
foreach (ServiceEndpoint se in selfhost.Description.Endpoints)
Console.WriteLine("Service is host with endpoint " + se.Address);
//foreach (ServiceEndpoint se in webHost.Description.Endpoints)
// Console.WriteLine("Service is host with endpoint " + se.Address);
//Console.WriteLine("ASP.Net : " + ServiceHostingEnvironment.AspNetCompatibilityEnabled);
Console.WriteLine("Host is running... Press <Enter> key to stop");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
}
我还没有尝试使用依赖注入技术与 WCF 集成,也许该博客中的解决方案值得一试。我也不建议您在 WCF 中使用依赖注入,因为它本身不支持依赖注入。此外,对于 servicehost
托管 WCF REST-style
服务,我们需要在服务端点上添加 WebHttp
行为。请参考以下代码实现。
Uri uri = new Uri("http://localhost:8004");
WebHttpBinding binding = new WebHttpBinding();
binding.Security.Mode = WebHttpSecurityMode.None;
using (ServiceHost sh = new ServiceHost(typeof(MyService), uri))
{
ServiceEndpoint se=sh.AddServiceEndpoint(typeof(IService), binding,"");
se.EndpointBehaviors.Add(new WebHttpBehavior());
sh.Opened += delegate
{
Console.WriteLine("Service is ready");
};
sh.Closed += delegate
{
Console.WriteLine("Service is clsoed");
};
sh.Open();
Console.ReadLine();
//pause
sh.Close();
Console.ReadLine();
如果有什么我可以帮忙的,请随时告诉我。
我需要一些示例来说明如何在自托管环境中使用 WCF 技术并使用 DI 容器(可能是 SimpleInjector)实现 RESTfull 服务。
在 https://simpleinjector.readthedocs.io/en/latest/wcfintegration.html 我找到了如何集成自定义工厂,但它是为 ServiceHost 制作的,但这不适合使用 WebServiceHost 的 RESTFull 服务?
我尝试将服务主机配置为与 webHttpBinding 兼容,但没有任何反应,我收到此类错误:
<Fault
xmlns="http://schemas.microsoft.com/ws/2005/05/envelope/none">
<Code>
<Value>Sender</Value>
<Subcode>
<Value
xmlns:a="http://schemas.microsoft.com/ws/2005/05/addressing/none">a:DestinationUnreachable
</Value>
</Subcode>
</Code>
<Reason>
<Text xml:lang="it-IT">Impossibile elaborare nel destinatario il messaggio con To 'http://localhost:8733/3AdispPushBatchService/pushpost' a causa di una mancata corrispondenza AddressFilter in EndpointDispatcher. Controllare la corrispondenza di EndpointAddresses del mittente e del destinatario.</Text>
</Reason>
</Fault>
是否有另一个集成包可用于 WebServiceHost?
这是我做的例子
AAADispPushBatchService.cs
using System;
using System.Configuration;
using System.IO;
using System.ServiceModel.Activation;
using System.Text;
using Newtonsoft.Json;
namespace AAARestService
{
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class AAADispPushBatchService : IAaaDispPushBatchService
{
public string GetBatchJson(Stream jsonFileContent)
{
try
{
var sr = new StreamReader(jsonFileContent, Encoding.UTF8);
var str = sr.ReadToEnd();
if (String.IsNullOrWhiteSpace(str))
throw new ArgumentException("No data inside body request");
var definition = new { BatchName = "" };
var json = JsonConvert.DeserializeAnonymousType(str, definition);
if (json == null)
throw new ArgumentException("No valid json inside");
if (String.IsNullOrWhiteSpace(json.BatchName))
throw new ArgumentException("BatchName not present");
var currentDir = ConfigurationManager.AppSettings["BatchPath"];
Directory.CreateDirectory(currentDir);
var filepath = Path.Combine(currentDir, json.BatchName+".json");
File.WriteAllText(filepath, str);
return $"Saved in {filepath}";
}
catch (Exception e)
{
return e.Message;
}
}
}
}
IAaaDispPushBatchService.cs
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Web;
namespace AAARestService
{
[ServiceContract(Name = "AAADispPushBatchService")]
public interface IAaaDispPushBatchService
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "pushpost", BodyStyle = WebMessageBodyStyle.Bare,ResponseFormat = WebMessageFormat.Json)]
string GetBatchJson(Stream jsonFileContent);
}
}
编辑!!!!!! 顺便说一句,我尝试在此处添加 simpleinjector,这是基于我在博客中找到的示例
Bootstrapper.cs
using System.Reflection;
using SimpleInjector;
namespace AAARestService
{
public static class BootStrapper
{
public static readonly Container Container;
static BootStrapper()
{
Container container = new Container();
container.Register<IMyDateTimeService,MyDAteTimeService>();
container.RegisterWcfServices(Assembly.GetExecutingAssembly());
Container = container;
}
}
}
MyWebServiceHostFactory.cs
public class MyWebServiceHostFactory : SimpleInjectorServiceHostFactory
{
public ServiceHost GetWebServiceEndpoint(Type serviceType,Uri baseAddress)
{
Uri[] addresses=new Uri[]{baseAddress};
var service = CreateServiceHost(serviceType, addresses);
ServiceEndpoint sep = service.AddServiceEndpoint(typeof(IAaaDispPushBatchService), new WebHttpBinding(), baseAddress);
sep.EndpointBehaviors.Add(new WebHttpBehavior());
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
service.Description.Behaviors.Add(smb);
return service;
}
protected override ServiceHost CreateServiceHost(Type serviceType,
Uri[] baseAddresses)
{
var host = new SimpleInjectorServiceHost(
BootStrapper.Container,
serviceType,
baseAddresses);
return host;
}
}
主要
static void Main(string[] args)
{
try
{
Uri httpUrl = new Uri("http://localhost:8733/3AdispPushBatchService");
Uri httpUrl1 = new Uri("http://localhost:8734/3AdispPushBatchService");
//ServiceHost selfhost = new ServiceHost(typeof(AAADispPushBatchService), httpUrl);
//ServiceEndpoint sep =selfhost.AddServiceEndpoint(typeof(IAaaDispPushBatchService),new WebHttpBinding(), httpUrl);
//sep.EndpointBehaviors.Add(new WebHttpBehavior());
//ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
//smb.HttpGetEnabled = true;
//selfhost.Description.Behaviors.Add(smb);
MyWebServiceHostFactory factory = new MyWebServiceHostFactory();
var selfhost=factory.GetWebServiceEndpoint(typeof(AAADispPushBatchService), httpUrl);
selfhost.Open();
//WebServiceHost webHost = new WebServiceHost(typeof(AAADispPushBatchService),httpUrl1);
//webHost.Open();
foreach (ServiceEndpoint se in selfhost.Description.Endpoints)
Console.WriteLine("Service is host with endpoint " + se.Address);
//foreach (ServiceEndpoint se in webHost.Description.Endpoints)
// Console.WriteLine("Service is host with endpoint " + se.Address);
//Console.WriteLine("ASP.Net : " + ServiceHostingEnvironment.AspNetCompatibilityEnabled);
Console.WriteLine("Host is running... Press <Enter> key to stop");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
}
我还没有尝试使用依赖注入技术与 WCF 集成,也许该博客中的解决方案值得一试。我也不建议您在 WCF 中使用依赖注入,因为它本身不支持依赖注入。此外,对于 servicehost
托管 WCF REST-style
服务,我们需要在服务端点上添加 WebHttp
行为。请参考以下代码实现。
Uri uri = new Uri("http://localhost:8004");
WebHttpBinding binding = new WebHttpBinding();
binding.Security.Mode = WebHttpSecurityMode.None;
using (ServiceHost sh = new ServiceHost(typeof(MyService), uri))
{
ServiceEndpoint se=sh.AddServiceEndpoint(typeof(IService), binding,"");
se.EndpointBehaviors.Add(new WebHttpBehavior());
sh.Opened += delegate
{
Console.WriteLine("Service is ready");
};
sh.Closed += delegate
{
Console.WriteLine("Service is clsoed");
};
sh.Open();
Console.ReadLine();
//pause
sh.Close();
Console.ReadLine();
如果有什么我可以帮忙的,请随时告诉我。