I have server code that has been shelved for awhile and I went back to test it.
We create a ServiceHost in a class and we add endpoints to the ServiceHost. When we add an endpoint we are getting an exception saying:
[the ServiceContract attribute cannot be found.]
But the attribute is there and I have added code to get the attributes and verify it is there.
public static void AddEndPoint ( ServiceHost host, string url, Type implementsType )
{
var binding = CreateBinding( url );
var attrs = implementsType.GetCustomAttributes ( false );
host.AddServiceEndpoint ( implementsType, binding, url );
}
[ServiceContract]
public interface IHelloWorldService
{
[OperationContract]
string SayHello ( string name );
}
I have created an example sln that works fine where all libraries are .net framework libraries.
In regular sln our service interfaces are in a .net standard 2.0 library, our services are in a .net framework library and the project that creates the service host is a .net framework library. I cannot figure out why if the attribute is there when viewed in the attrs array and yet AddServiceEndPoint does not find it.
Related
I have the following :
a class library with connection classes such as connection, command, parameter
a DAL with entities, mapper, interface, services as well as a static class that holds hard coded connectionString and InvariantName.
an Asp.Net Core project
References :
DAL has a reference to the class library to make use of its connection class to which it provides connectionString and InvariantName thanks to its static class etc..
Asp.Net has a reference to the DAL.
What I want :
I now want to use the User Secrets to store hard coded sensitive data connections and get rid off the static class.
I know I can use the the Asp.Net Core startup.cs to read the settings from Configuration and make use of binding to store them into a class and use DI.
My guess :
DI seems "easy" when used inside an Asp controller. But I need the settings values (connectionString and InvariantName) outside the Asp.Net Core to be injected into a constructor of a class somewhere in my DAL.
I guess I would then need to have to reference the Asp.Net Core project to my DAL. But then I would end up with a circular reference (DAL to Asp.Net Core and the opposite).
So what's the solution?
Have an intermediate library class into which I would retreive the settings values from Asp.Net Core and then pass them to my DAL (to prevent circular reference)?
Manually recreate the "Configuration process" inside the DAL and get settings there directly
Or something else that I don't know?
Ps : I am new in development and only have a few projects'experience in Asp.Net Framework so far..and it's my first Asp.Net Core project
I know I can use the the Asp.Net Core startup.cs to read the settings from Configuration and make use of binding to store them into a class and use DI
You already answered your own question with this. This is the correct and recommended behavior to setup DI for 3rd party libs and configurations. If you want to avoid clutter in Startup class, create an extension method:
namespace Microsoft.Extensions.DependencyInjetion
{
public static MyLibraryCollectionExtensions
{
public static IServiceCollection AddMyLibrary(this IServiceCollection services)
{
services.AddDbContext<MyDbContext>(...);
}
}
}
to register your classes. Alternatively, extend the method to accept a parameter delegate to configure it
namespace Microsoft.Extensions.DependencyInjetion
{
public static MyLibraryCollectionExtensions
{
public static IServiceCollection AddMyLibrary(this IServiceCollection services, Action<MyOptions> setup)
{
var defaultOptions = ... // i.e. new MyOptions();
// pass default options to be modified by the delegate
setup?.Invoke(defaultOptions);
// your registrations
services.AddDbContext<MyDbContext>(...);
}
}
}
And all the user has to do in your library is add
services.AddMyLibrary();
// or with setup
services.AddMyLibrary(config =>
{
config.MyConnectionString = Configuration.GetConnectionString("MyContext");
});
and store the connection string in the appsettings.json.
{
"ConnectionStrings":
{
"MyContext" : "MyConnectionString here"
}
}
I finally used the ConfigurationBuilder to get values from the appsettings.json file.
It's probably not the right way to do it but it is working with my DAL and Connection dlls.
In case it helps anyone else :
I just begun to do Xamarin.Forms with .Net Standard 2.0 (PCL) project. I'm trying to consume my WCF web service but never got it successfully done.
I have created a simple WCF as below
[ServiceContract]
public interface IWcfConnection
{
[OperationContract]
string GetHelloWorld();
}
the implementation as below
public class WcfConnection : IWcfConnection
{
public string GetHelloWorld()
{
return "Hello World";
}
}
It's a very simple WCF, when I go to my Xamarin.Forms and right click on the "Connected Service", there is no "Add Web Service", but only "Add Connected Service", so I selected that as below
Then select "Microsoft WCF Web Service Service Provider"
Select the option as below (I untick everything because if I add more than 1 service, it will crash)
When I look into the reference.cs created, there is only async method created.
public System.Threading.Tasks.Task<string> GetHelloWorldAsync()
{
return base.Channel.GetHelloWorldAsync();
}
1) May I know why only async is created? Is it for .net standard and core, only async services will be created? As I read somewhere.
2) If so, how do I consume the web service?
In my xaml.cs file, I did the following,
WcfConnectionService.WcfConnectionClient client = new WcfConnectionService.WcfConnectionClient(new WcfConnectionService.WcfConnectionClient.EndpointConfiguration());
string abc = client.GetHelloWorldAsync().GetAwaiter().GetResult();
But I'm getting error and unable to work accordingly. Anybody got any idea?
Unhandled Exception:
System.ServiceModel.FaultException`1[[System.ServiceModel.ExceptionDetail, System.ServiceModel, Version=2.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: Error in deserializing body of request message for operation 'GetHelloWorld'. OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name 'GetHelloWorld' and namespace 'http://tempuri.org/'. Found node type 'Element' with name 'GetHelloWorldAsync' and namespace 'http://tempuri.org/'
At the moment Xamarin apps aren't compatible with the Task-based asynchronous WCF proxy methods that the WCF Web Service Reference connected service provider generates for .NET Standard projects (bugzilla.xamarin.com Bug 51959).
Generate an older compatible style of WCF proxy methods via checked "Generate Synchronous Operations" checkbox on Configure WCF Web Service Reference screen:
Consume the web service:
KimlikServiceReference.KPSPublicSoapClient soapClient = new KimlikServiceReference.KPSPublicSoapClient(KimlikServiceReference.KPSPublicSoapClient.EndpointConfiguration.KPSPublicSoap);
//KimlikServiceReference.TCKimlikNoDogrulaResponse response = soapClient.TCKimlikNoDogrulaAsync(TCKimlikNo, Ad, Soyad, DogumYili).Result;
bool result = soapClient.TCKimlikNoDogrula(TCKimlikNo, Ad, Soyad, DogumYili);
I have a WCF service that is defined in a module. When we try to call this service from a non-default tenant, the content manager always references our default tenants settings. In debugging, inside of OrchardServiceHostFactory,
I notice that it ends up getting the settings for the default tenant because the base address that is passed into the CreateServiceHost method is always our default tenants uri.
Given that I am not wholly familiar with WCF, is there a configuration option that I am missing that is causing the WCF service to be created with the default tenants address, instead of the non-default tenant?
Relevant code:
private static readonly Route _SITEMAP_SERVICE_ROUTE = new ServiceRoute("api/SitemapService", new OrchardServiceHostFactory(), typeof(ISitemapService))
{
DataTokens = new RouteValueDictionary
{
{
"area", "Project.Localization"
}
}
};
public interface ISitemapService : IOrchardSitemapService, IDependency
{
}
[ServiceContract]
public interface IOrchardSitemapService
{
[OperationContract]
int GetNavigableContentCount();
[OperationContract]
List<SitemapEntry> GetNavigableContent();
}
I was able to fix this by adding an additional site to IIS that pointed to the same file system location, and used the same application pool. This new site then references the non-default's tenant, and the service will now be created with the correct base address.
With .NET 4.5, my WCF creation using svcutil suddenly seems to break (I've been using only .NET 4.0 until very recently) ....
With the default settings I'm using to convert a pre-existing WSDL to my C# WCF proxy class:
c:> svcutil.exe /n:*,MyNamespace /out:WebService MyService.wsdl
I get this C# file created:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="MyService.IMyService1")]
public interface IMyService1
{
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IMyService1/IsAlive", ReplyAction="http://tempuri.org/IMyService1/IsAliveResponse")]
[System.ServiceModel.FaultContractAttribute(typeof(MyService.MyFault), Action="http://tempuri.org/IMyService1/IsAliveErrorInfoFault", Name="MyServiceErrorInfo", Namespace="http://schemas.datacontract.org/2004/07/MyService.Types")]
string IsAlive();
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IMyService1/IsAlive", ReplyAction="http://tempuri.org/IMyService1/IsAliveResponse")]
System.Threading.Tasks.Task<string> IsAliveAsync();
This doesn't work - if I try to instantiate an implemention of this interface in a ServiceHost
using (ServiceHost svcHost = new ServiceHost(typeof(MyService01Impl)))
{
svcHost.Open();
Console.WriteLine("Host running ...");
Console.ReadLine();
svcHost.Close();
}
I get this error:
Cannot have two operations in the same contract with the same name, methods 'IsAlive' and 'IsAliveAsync' in type 'MyService01Impl' violate this rule. You can change the name of one of the operations by changing the method name or by using the Name property of OperationContractAttribute.
Why does svcutil suddenly generate code that doesn't work??
If I use the /async keyword with svcutil, then I get the "old-style" async pattern with BeginIsAlive and EndIsAlive and things work again - but how can I tell WCF / svcutil to generate no async stuff at all?
svcutil by default generates a proxy class with both synchronous and Task-based methods, eg:
public interface IService1
{
...
string GetData(int value);
...
System.Threading.Tasks.Task<string> GetDataAsync(int value);
...
}
To generate a proxy with only synchronous methods, you need to use /syncOnly. This will omit the Task-based version:
public interface IService1
{
...
string GetData(int value);
...
}
In both cases, the proxy class itself inherits from ClientBase:
public partial class Service1Client : System.ServiceModel.ClientBase<IService1>, IService1
Finally, the /serviceContract switch generates only the interface and DTOs necessary for generating a dummy service
I'm new to WCF and trying to get my first service running. I'm close but stuck on this problem.
In my interface definition file, I have this:
[ServiceContract(Namespace="http://mysite.com/wcfservices/2009/02")]
public interface IInventoryService
{
[OperationContract]
string GetInventoryName(int InventoryID);
}
Then I have my class file (for the service) that inherits it:
public class InventoryService : IInventoryService
{
// This method is exposed to the wcf service
public string GetInventoryName(int InventoryID)
{
return "White Paper";
}
Finally, in my Host project I have this:
ServiceHost host = new ServiceHost(typeof(Inventory.InventoryService));
host.AddServiceEndpoint(typeof(Inventory.InventoryService), new NetTcpBinding(),
"net.tcp://localhost:9000/GetInventory");
host.Open();
Everything compiles fine, and when the host goes to add the service endpoint, it bombs with this: "The contract type Inventory.InventoryService is not attributed with ServiceContractAttribute. In order to define a valid contract, the specified type (either contract interface or service class) must be attributed with ServiceContractAttribute."
I know I'm missing something simple here. I have the interface clearly marked as a service contract and there's a reference to that project in the Host project.
ServiceHost host = new ServiceHost(typeof(Inventory.InventoryService));
host.AddServiceEndpoint(typeof(Inventory.InventoryService), new NetTcpBinding(),
"net.tcp://localhost:9000/GetInventory");
host.Open();
If your ServiceContract attribute is on the Interface not the concrete class, try the following:
ServiceHost host = new ServiceHost(typeof(Inventory.InventoryService));
host.AddServiceEndpoint(typeof(Inventory.IInventoryService), new NetTcpBinding(),
"net.tcp://localhost:9000/GetInventory");
host.Open();