运行 没有 App.config 的 wcf 服务不工作
Running wcf service without App.config doesn't work
我在控制台应用程序中创建了简单的 wcf 主机。它不起作用,异常使没有意义:/
异常看起来真的很奇怪:
"ContractDescription 'IFooService' has zero operations; a contract
must have at least one operation."
因为,这是代码,我有一个操作:
[ServiceContract]
public interface IFooService
{
[OperationContract]
void DoNothing();
[OperationContract]
int GetFoo(int i);
}
public class FooService : IFooService
{
public void DoNothing()
{
}
public int GetFoo(int i)
{
return i + 1;
}
}
class Program
{
static void Main(string[] args)
{
try
{
string address = "http://localhost:9003/FooService";
Uri addressBase = new Uri(address);
var svcHost = new ServiceHost(typeof(FooService), addressBase);
BasicHttpBinding bHttp = new BasicHttpBinding();
Type contractType = typeof(IFooService);
ContractDescription contractDescription = new ContractDescription(contractType.Name);
contractDescription.ProtectionLevel = ProtectionLevel.None;
contractDescription.ContractType = contractType;
contractDescription.ConfigurationName = contractType.FullName;
contractDescription.SessionMode = SessionMode.NotAllowed;
svcHost.AddServiceEndpoint(new ServiceEndpoint(contractDescription, bHttp, new EndpointAddress(address)));
svcHost.Open();
Console.WriteLine("\n\nService is Running as >> " + address);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadKey();
}
}
这基本上是完整的代码。 App.config 保持不变:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>
编辑: 一点线索,它是这样工作的:我没有更改服务或合同,但将配置移动到 App.config,所以只更改了 Main 方法:
App.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<system.serviceModel>
<services>
<service name="WcfDemos.ConsoleHost.FooService">
<endpoint address="http://localhost:9003/FooService" binding="basicHttpBinding"
contract="WcfDemos.ConsoleHost.IFooService" />
</service>
</services>
</system.serviceModel>
</configuration>
主要:
static void Main(string[] args)
{
try
{
string address = "http://localhost:9003/FooService";
Uri addressBase = new Uri(address);
var svcHost = new ServiceHost(typeof(FooService), addressBase);
svcHost.Open();
Console.WriteLine("\n\nService is Running as >> " + address);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadKey();
}
为什么需要使用 ContractDescription?我想它会在配置文件中查找设置。
您可以执行以下操作(使用不带 ContractDescription 的 AddServiceEndpoint 方法):
static void Main(string[] args)
{
try
{
string address = "http://localhost:9003/FooService";
Uri addressBase = new Uri(address);
var svcHost = new ServiceHost(typeof(FooService), addressBase);
BasicHttpBinding bHttp = new BasicHttpBinding();
//Type contractType = typeof(IFooService);
//ContractDescription contractDescription = new ContractDescription(contractType.Name);
//contractDescription.ProtectionLevel = ProtectionLevel.None;
//contractDescription.ContractType = contractType;
//contractDescription.ConfigurationName = contractType.FullName;
//contractDescription.SessionMode = SessionMode.NotAllowed;
//svcHost.AddServiceEndpoint(new ServiceEndpoint(contractDescription, bHttp, new EndpointAddress(address)));
svcHost.AddServiceEndpoint(typeof(IFooService).ToString(), bHttp, address);
svcHost.Open();
Console.WriteLine("\n\nService is Running as >> " + address);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadKey();
}
顺便说一下,您可以在这里找到一些用于配置 WCF 服务的库,而无需 app.config 文件:WCF NetTcpBinding Bootcamp
我认为如果您不在配置文件中提供端点,则必须将端点添加到 ServiceHost。查看 AddServiceEndpoint
调用:
Uri baseAddr = new Uri("http://localhost:8000/WCFService1");
ServiceHost localHost = new ServiceHost(typeof(CalculatorService), baseAddr);
try
{
localHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "CalculatorService");
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
localHost.Description.Behaviors.Add(smb);
localHost.Open();
Console.WriteLine("Service initialized.");
Console.WriteLine("Press the ENTER key to terminate service.");
Console.WriteLine();
Console.ReadLine();
localHost.Close();
}
catch (CommunicationException ex)
{
Console.WriteLine("Oops! Exception: {0}", ex.Message);
localHost.Abort();
}
http://www.programminghelp.com/dotnet/wcf-creating-and-implementing-a-service-in-c/
以上来自微软例子:
https://docs.microsoft.com/en-us/dotnet/framework/wcf/how-to-host-and-run-a-basic-wcf-service
这是一个很好的起点。尽管如此......仍然不清楚需要在代码中添加什么才能使下面的app.config内容变得多余:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" />
</system.web>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<system.serviceModel>
<services>
<service name="GettingStartedLib.CalculatorService">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:8000/GettingStarted/CalculatorService" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address="" binding="wsHttpBinding" contract="GettingStartedLib.ICalculator">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<!-- Metadata Endpoints -->
<!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. -->
<!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information,
set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
我在控制台应用程序中创建了简单的 wcf 主机。它不起作用,异常使没有意义:/ 异常看起来真的很奇怪:
"ContractDescription 'IFooService' has zero operations; a contract must have at least one operation."
因为,这是代码,我有一个操作:
[ServiceContract]
public interface IFooService
{
[OperationContract]
void DoNothing();
[OperationContract]
int GetFoo(int i);
}
public class FooService : IFooService
{
public void DoNothing()
{
}
public int GetFoo(int i)
{
return i + 1;
}
}
class Program
{
static void Main(string[] args)
{
try
{
string address = "http://localhost:9003/FooService";
Uri addressBase = new Uri(address);
var svcHost = new ServiceHost(typeof(FooService), addressBase);
BasicHttpBinding bHttp = new BasicHttpBinding();
Type contractType = typeof(IFooService);
ContractDescription contractDescription = new ContractDescription(contractType.Name);
contractDescription.ProtectionLevel = ProtectionLevel.None;
contractDescription.ContractType = contractType;
contractDescription.ConfigurationName = contractType.FullName;
contractDescription.SessionMode = SessionMode.NotAllowed;
svcHost.AddServiceEndpoint(new ServiceEndpoint(contractDescription, bHttp, new EndpointAddress(address)));
svcHost.Open();
Console.WriteLine("\n\nService is Running as >> " + address);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadKey();
}
}
这基本上是完整的代码。 App.config 保持不变:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>
编辑: 一点线索,它是这样工作的:我没有更改服务或合同,但将配置移动到 App.config,所以只更改了 Main 方法:
App.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<system.serviceModel>
<services>
<service name="WcfDemos.ConsoleHost.FooService">
<endpoint address="http://localhost:9003/FooService" binding="basicHttpBinding"
contract="WcfDemos.ConsoleHost.IFooService" />
</service>
</services>
</system.serviceModel>
</configuration>
主要:
static void Main(string[] args)
{
try
{
string address = "http://localhost:9003/FooService";
Uri addressBase = new Uri(address);
var svcHost = new ServiceHost(typeof(FooService), addressBase);
svcHost.Open();
Console.WriteLine("\n\nService is Running as >> " + address);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadKey();
}
为什么需要使用 ContractDescription?我想它会在配置文件中查找设置。 您可以执行以下操作(使用不带 ContractDescription 的 AddServiceEndpoint 方法):
static void Main(string[] args)
{
try
{
string address = "http://localhost:9003/FooService";
Uri addressBase = new Uri(address);
var svcHost = new ServiceHost(typeof(FooService), addressBase);
BasicHttpBinding bHttp = new BasicHttpBinding();
//Type contractType = typeof(IFooService);
//ContractDescription contractDescription = new ContractDescription(contractType.Name);
//contractDescription.ProtectionLevel = ProtectionLevel.None;
//contractDescription.ContractType = contractType;
//contractDescription.ConfigurationName = contractType.FullName;
//contractDescription.SessionMode = SessionMode.NotAllowed;
//svcHost.AddServiceEndpoint(new ServiceEndpoint(contractDescription, bHttp, new EndpointAddress(address)));
svcHost.AddServiceEndpoint(typeof(IFooService).ToString(), bHttp, address);
svcHost.Open();
Console.WriteLine("\n\nService is Running as >> " + address);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadKey();
}
顺便说一下,您可以在这里找到一些用于配置 WCF 服务的库,而无需 app.config 文件:WCF NetTcpBinding Bootcamp
我认为如果您不在配置文件中提供端点,则必须将端点添加到 ServiceHost。查看 AddServiceEndpoint
调用:
Uri baseAddr = new Uri("http://localhost:8000/WCFService1");
ServiceHost localHost = new ServiceHost(typeof(CalculatorService), baseAddr);
try
{
localHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "CalculatorService");
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
localHost.Description.Behaviors.Add(smb);
localHost.Open();
Console.WriteLine("Service initialized.");
Console.WriteLine("Press the ENTER key to terminate service.");
Console.WriteLine();
Console.ReadLine();
localHost.Close();
}
catch (CommunicationException ex)
{
Console.WriteLine("Oops! Exception: {0}", ex.Message);
localHost.Abort();
}
http://www.programminghelp.com/dotnet/wcf-creating-and-implementing-a-service-in-c/
以上来自微软例子:
https://docs.microsoft.com/en-us/dotnet/framework/wcf/how-to-host-and-run-a-basic-wcf-service
这是一个很好的起点。尽管如此......仍然不清楚需要在代码中添加什么才能使下面的app.config内容变得多余:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" />
</system.web>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<system.serviceModel>
<services>
<service name="GettingStartedLib.CalculatorService">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:8000/GettingStarted/CalculatorService" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address="" binding="wsHttpBinding" contract="GettingStartedLib.ICalculator">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<!-- Metadata Endpoints -->
<!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. -->
<!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information,
set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>