增加WebService支持类。

This commit is contained in:
falcon 2023-02-16 15:25:37 +08:00
parent 207e944d02
commit c9c3211c45
6 changed files with 200 additions and 0 deletions

View File

@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="SoapCore" Version="1.1.0.36" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,65 @@
## WebService服务器帮助
### 服务端
1. 首先使用IServiceCollection.AddWebServices注册服务及其实现。
2. 使用IApplicationBuilder.UseRouting()应用路由中间价。
3. 调用IApplicationBuilder.UseWebServiceEndpoint方法应用中间件。
### 客户端
1. 调用WebServiceClient.CreateWebServiceClient<T>方法创建客户端。T为服务端应以的协议接口返回T协议对应的通信实现。
### 实例
服务端:
~~~c#
/// <summary>
/// Web服务协议
/// </summary>
[ServiceContract]
public interface IWebSvc
{
[OperationContract]
public string HellowWorld(string name);
}
public class WebSvc:IWebSvc
{
public string HellowWorld(string name) {
return $"Hellow world {name}!";
}
}
using Falcon.SugarApi.WebService;
using Server;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddWebService<IWebSvc,WebSvc>();
var app = builder.Build();
app.UseRouting();
app.UseWebServiceEndpoint<IWebSvc>("/WebService.asmx");
app.Run();
~~~
客户端:
~~~c#
using System.ServiceModel;
[ServiceContractAttribute(ConfigurationName = "Service.IWebSvc")]
internal interface IWebSvc
{
[OperationContractAttribute(Action = "http://tempuri.org/IWebSvc/HellowWorld",ReplyAction = "http://tempuri.org/IWebSvc/HellowWorldResponse")]
Task<string> HellowWorldAsync(string name);
}
using Falcon.SugarApi.WebService;
var svc = WebServiceClient.CreateWebServiceClient<IWebSvc>("http://localhost:5000/WebService.asmx");
var result=await svc.HellowWorldAsync("Jeck");
~~~

View File

@ -0,0 +1,31 @@
using System.ServiceModel;
namespace Falcon.SugarApi.WebService
{
/// <summary>
/// WebService客户端
/// </summary>
public static class WebServiceClient
{
/// <summary>
/// 创建一个符合<typeparamref name="T"/>协议的WebService客户端
/// </summary>
/// <typeparam name="T">协议</typeparam>
/// <param name="url">服务端地址</param>
/// <param name="builder">创建器</param>
/// <returns>实例化的协议通信客户端</returns>
/// <exception cref="ArgumentNullException"></exception>
public static T CreateWebServiceClient<T>(string url,Action<WebServiceClientOption>? builder = null) {
url=url??throw new ArgumentNullException("url must is not null.");
var bind = new BasicHttpBinding {
MaxBufferSize=int.MaxValue,
ReaderQuotas=System.Xml.XmlDictionaryReaderQuotas.Max,
MaxReceivedMessageSize=int.MaxValue,
AllowCookies=true,
};
var option = new WebServiceClientOption { Address=url,Binding=bind };
builder?.Invoke(option);
return (new ChannelFactory<T>(option.Binding,new EndpointAddress(option.Address))).CreateChannel();
}
}
}

View File

@ -0,0 +1,20 @@
using System.ServiceModel.Channels;
namespace Falcon.SugarApi.WebService
{
/// <summary>
/// WebService客户端配置
/// </summary>
public class WebServiceClientOption
{
/// <summary>
/// 绑定
/// </summary>
public Binding? Binding { get; set; }
/// <summary>
/// 服务端地址
/// </summary>
public string? Address { get; set; }
}
}

View File

@ -0,0 +1,66 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using SoapCore;
using System.Xml;
namespace Falcon.SugarApi.WebService
{
/// <summary>
/// 扩展服务集合和应用程序支持WebService
/// </summary>
public static class WebServiceExtend
{
/// <summary>
/// 添加基于Soap协议的WebService服务
/// </summary>
/// <typeparam name="Tservice">服务类型</typeparam>
/// <typeparam name="TImplementation">实现类</typeparam>
/// <param name="services">服务集合</param>
/// <returns>服务集合</returns>
public static IServiceCollection AddWebService<Tservice, TImplementation>(this IServiceCollection services)
where Tservice : class where TImplementation : class, Tservice {
services.AddSoapCore();
services.TryAddSingleton<Tservice,TImplementation>();
return services;
}
/// <summary>
/// 添加基于Soap协议的WebService服务组
/// </summary>
/// <param name="services">服务集合</param>
/// <param name="descriptors">要添加的WebService服务说明</param>
/// <returns>服务集合</returns>
public static IServiceCollection AddWebServices(this IServiceCollection services,params ServiceDescriptor[] descriptors) {
services.AddSoapCore();
if(descriptors==null||descriptors.Length==0) {
return services;
}
foreach(var des in descriptors.Where(d => d!=null)) {
services.TryAddSingleton(des);
}
return services;
}
/// <summary>
/// 增加WebService终结点。在此之前必须首先UseRouting()。
/// </summary>
/// <typeparam name="TService">终结点服务</typeparam>
/// <param name="application">应用创建器</param>
/// <param name="url">终结点url</param>
/// <returns>终结点服务</returns>
public static IApplicationBuilder UseWebServiceEndpoint<TService>(this IApplicationBuilder application,string url="/WebSvc.asmx") {
var xnm = new XmlNamespaceManager(new NameTable());
xnm.AddNamespace("soap","http://schemas.xmlsoap.org/soap/envelope/");
xnm.AddNamespace("xsi","http://www.w3.org/2001/XMLSchema-instance");
xnm.AddNamespace("xsd","http://www.w3.org/2001/XMLSchema");
application.UseEndpoints(endpoints => {
endpoints.UseSoapEndpoint<TService>(url,
new SoapEncoderOptions() { XmlNamespaceOverrides=xnm },
SoapSerializer.DataContractSerializer,
omitXmlDeclaration: false,
indentXml: false);
});
return application;
}
}
}

View File

@ -13,6 +13,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
README.md = README.md
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Falcon.SugarApi.WebService", "Falcon.SugarApi.WebService\Falcon.SugarApi.WebService.csproj", "{A02586C2-B485-47C3-988B-AC050BD2286C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -27,6 +29,10 @@ Global
{EADC8D8F-449C-4C4C-8168-0075B333494B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EADC8D8F-449C-4C4C-8168-0075B333494B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EADC8D8F-449C-4C4C-8168-0075B333494B}.Release|Any CPU.Build.0 = Release|Any CPU
{A02586C2-B485-47C3-988B-AC050BD2286C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A02586C2-B485-47C3-988B-AC050BD2286C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A02586C2-B485-47C3-988B-AC050BD2286C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A02586C2-B485-47C3-988B-AC050BD2286C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE