Adding IClientMessageInspector globally to any service reference - c#

I Have a .net solution with two seperate projects,
one is a class library and other as a web application.
All of my Service References placed in my class library project. and all bindings and endpoint configurations done programmatically.
In my Web Application I Added a IClientMessageInspector and BehaviorExtensionElement by reading this link. How to: Inspect or Modify Messages on the Client
I Don't want to add dbcontext access from within my class library, and all my db operations done at web application project.
Now the problem is I want to log every outgoing service call that place in my class library and I Want to configure this globally. (log to db)
for old style web references I was able to add a Soap Extention like the image below, and all calls logged using TraceExtention class.
I need the same ability using Service References.

You can do the same with WCF by adding behavior extensions to web.config.
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="ClientBehavior">
<ClientEndpointBehavior />
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="ClientEndpointBehavior" type="Custom.WCFMessageInspector, Custom" />
</behaviorExtensions>
</extensions>
</system.serviceModel>
1- Custom.WCFMessageInspector is where your client inspection code reside.
2- Add behaviorConfiguration="ClientBehavior" to the client endpoint.

Related

Adding an endpoint behavior extension through code

I have a WCF web service, self hosted, configured through the configuration file.
I want to add an endpoint behavior extension to one of my endpoint behaviors programmatically. Adding it through the configuration file is very easy.
<extensions>
<behaviorExtensions>
<add name="EnableCors" type="CorsEnablingExtension.EnableCorsSupportBehaviorElement, CorsEnablingExtension"/>
</behaviorExtensions>
</extensions>
<behaviors>
<endpointBehaviors>
<behavior name="SoapBehavior"/>
<behavior name="RestBehavior">
<CustomBehavior/>
<EnableCors/>
</behavior>
</endpointBehaviors>
</behaviors>
So I can just throw EnableCors in there and everything's fine. But I want to add a delegate parameter in the behavior constructor so I'd like to add it through code, but keep all the other configuration elements.
If I add a static Configure method in my service implementation
public static void Configure(ServiceConfiguration config)
then I have to do all of the configuration programmatically which is too much hassle.
So the question is, can I add that IEndpointBehavior programmatically and keep the rest of the configuration in the config file ?

IIS hosted wcf returns me blank page

I have a wcf application. It has "Service1.svc" file. In the web.config file I specified
http://localhost:2005/EmployeeService.svc
as an endpoint. When clicking browse from Visual Studio there is no problem. But, when I hosted it on IIS server I get a blank page. The interesting thing is, If I remove the address from the web. config this time I can see the service at this address.
http://localhost:2005/EmployeeService.svc
web.config file is as below:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="EmployeeServiceBehaviour">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="EmployeeServiceBehaviour" name="EmployeeConfiguration">
<endpoint address="http://localhost:2005/EmployeeService.svc" binding="basicHttpBinding"
bindingConfiguration="" contract="IEmployeeConfiguration" />
</service>
</services>
</system.serviceModel>
<system.web>
<compilation debug="true"/>
</system.web>
<system.webServer>
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
Could you please explain, why I get a blank page on IIS when I provide the adress.
This may happen in HTTP Activation is not installed in Programs and Features in your Windows installation. Check HTTP Activation for both .Net 3.5 and 4.6 to enable opening WCF service via HTTP request to .svc file hosted in IIS.
I think you can remove all text on the address before Service.svc. This might be an issue with different urls.
When you specify the address part, you tell WCF the service is only available on that address. When going through the endpoints, WCF will not find one that matches the given URL and bail out.
When you have multiple endpoints you need the address field. Otherwise you don't.
Read http://msdn.microsoft.com/en-us/library/ms733749(v=vs.110).aspx
And in particular this part:
When hosting with IIS, you do not manage the ServiceHost instance yourself. The base address is always the address specified in the .svc file for the service when hosting in IIS. So you must use relative endpoint addresses for IIS-hosted service endpoints. Supplying a fully-qualified endpoint address can lead to errors in the deployment of the service.
Check if Service attribute in SVC markup equals your implementation class.
Check endpoint contract name. It has to be exactly full name of your interface. Don't add assembly name, it won't work.
Check <serviceMetadata httpGetEnabled="true" />. If false, you get blank page too.
And 4th change which helped me (but I have no idea why): Remove behavior name <behavior name=""> and remove behaviorConfiguration attribute from service element. It becomes default so the behavior will be used anyway.
Be sure you made an Application Pool with active user like this: https://stackoverflow.com/a/19654633/2148387
Be sure you created Web Application where your WCF is hosted
Check if AppPool and WebApp are running
Enable Directory Browse in your Web.config like here: https://stackoverflow.com/a/19630263/2148387

How do i Consume WCF Data Service?

i have created a wcf service but i have used 3 projects for it;
1) ServiceLibrary (WCF library)
2) Web
3) ConsoleTestClient
my ServiceLibrary app.config file looks like this;
<system.serviceModel>
<services>
<service name="MrDAStoreJobs.ServiceLibrary.AdvertisementService">
<clear />
<endpoint address="basic"
binding="basicHttpBinding" bindingConfiguration=""
contract="MrDAStoreJobs.ServiceLibrary.Interface.IAdvertisementService" />
<endpoint name="mexHttpBinding"
contract="IMetadataExchange"
binding="mexHttpBinding"
address="mex" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:13758/" />
</baseAddresses>
</host>
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information,
set the value below to false before deployment -->
<serviceMetadata httpGetEnabled="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="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel> <br />
Now, to host this library, i have done the following settings in my Web.Config file of the Web Project.
The svc file name is WcfDataService1.svc
public class WcfDataService1 : DataService<AdvertisementService>
{
// This method is called only once to initialize service-wide policies.
public static void InitializeService(DataServiceConfiguration config)
{
config.UseVerboseErrors = true;
ServiceOperationRights.All);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
}
}
<system.serviceModel>
<services>
<service name="MrDAStoreJobs.ServiceLibrary.AdvertisementService">
<clear />
<endpoint address="basic"
binding="basicHttpBinding" bindingConfiguration=""
contract="MrDAStoreJobs.ServiceLibrary.Interface.IAdvertisementService" />
<endpoint name="mexHttpBinding"
contract="IMetadataExchange"
binding="mexHttpBinding"
address="mex" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:13758/WcfDataService1.svc" />
</baseAddresses>
</host>
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information,
set the value below to false before deployment -->
<serviceMetadata httpGetEnabled="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="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Now, when i test this service using directly (ServiceLibrary project) using WCF test client, i see the following and works everything great;
The issue is when i try to run my Web project(which i use as a host for wcf service). And then go to the console test client and want to add reference using add reference. I don't see my Get and Set methods (like test client)
Why i don't see my IAdvertisementService interface and the methods
Do i have to deploy this to actuall IIS?
To develop a service using ASP.NET, we must add the WebService attribute to the class and WebMethodAttribute to any of the class methods.
Example
[WebService]
public class Service : System.Web.Services.WebService
{
[WebMethod]
public string Test(string strMsg)
{
return strMsg;
}
}
To develop a service in WCF, we will write the following code:
[ServiceContract]
public interface ITest
{
[OperationContract]
string ShowMessage(string strMsg);
}
public class Service : ITest
{
public string ShowMessage(string strMsg)
{
return strMsg;
}
}
The ServiceContractAttribute specifies that an interface defines a WCF service contract,
OperationContract attribute indicates which of the methods of the interface defines the operations of the service contract.
A class that implements the service contract is referred to as a service type in WCF.
Hosting the Service
ASP.NET web services are compiled into a class library assembly and a service file with an extension .asmx will have the code for the service. The service file is copied into the root of the ASP.NET application and Assembly will be copied to the bin directory. The application is accessible using URL of the service file.
WCF Service can be hosted within IIS or WindowsActivationService.
Compile the service type into a class library
Copy the service file with an extension .SVC into a virtual directory and assembly into bin sub directory of the virtual directory.
Copy the web.config file into the virtual directory.
Client Development
Clients for the ASP.NET Web services are generated using the command-line tool WSDL.EXE.
WCF uses the ServiceMetadata tool (svcutil.exe) to generate the client for the service.
For more detail goto this link
http://www.codeproject.com/Articles/139787/What-s-the-Difference-between-WCF-and-Web-Services
Previous Post Removed:
Update:
The Microsoft Developer Network actually covers this in great detail, some of the resources they provide are:
Overview
Tutorial From Code Project
There are also several books that my solve this particular endeavor. Since someone stated that providing links to solve this issue doesn't truly answer your question I'll attempt to.
Inside Visual Studio click File, then proceed to New Project.
In the dialog expand Visual C#, Select Web and ASP.NET Web Forms Application.
Give your project a name of your choice NorthwindWeb.
At this point you've created a project; due to the complexity of a Service overlooking a tiny detail can be catastrophic in the outcome. That is why I'm starting from scratch.
In my example I'll link it to a Database. So I'll add a Ado.Net Entity Data Model. I'll name my model: NorthwindModel. I'm also going to generate based upon an existing Database. So up at this point just follow the Visual Studio Wizard. Choose your Database Objects within those tables, then Finish.
The important part, building my Data Service.
Project Add New Item.
Select Web and choose WCF Data Service.
Put a name, NorthwindCustomer- Then Add.
Locate the first Todo: Comment and remove the code then put:
public class DemonDbCustomer : DataService<demonDbEntities>
Then find the comments in the InitializeService Event Handler:
config.SetEntitySetAccessRule("*", EntitySetRights.All);
At this point hit CTRL + F5 to run the service. The browser will open and the XML Schema for the service will generate. In the Address Bar type in Customers at the end of the URL for NorthwindCustomers.svc and hit Enter.
** Sometimes Internet Explorer will mess this up, so additional troubleshooting may be required. **
Now we will create our Client Portion.
Add a New Project
Select Windows Forms Application
Name the file of your choice, NorthwindClient then click Ok.
In the Solution Explorer select the NorthwindClient Project and Set As Startup Project.
Right Click on Project: Add Service Reference Click Discover.
At this point your URL for NorthwindCustomers Service will appear in that Address field. This is generated from that .svc file.
Now we have to provide data binding to our service.
On the Data Menu we want to Show Data Sources.
Add New Data Source
Choose the type of Data Source and follow the Wizard (Click Object).
Select the Object you wish to bind.
Now at this point you just need to create a User Interface. To do so just simply drag your Customers Node from your Data Sources to the Form.
DataGridView
BindingSource
BindingNavigation
They are all added automatically. Then simply double click your Form and add the following to your Form1_Load Event Handler.
ServiceReference1.northwindModel.northwindEntities proxy = new
ServiceReference1.northwindModel.northwindEntities(new
Uri("http://localhost:53397/NorthwindCustomers.svc/"));
// As you see it pointed to our SVC file, because that includes our Address, Binding, Contract information.
this.customersBindingSource.DataSource = proxy.Customers;
Now in your Solution Explorer right click that NorthwindCustomers.svc and click View In Browser. The XML Schema will be added, so you just copy that URL from the Address Bar. Then replace the Uri with the one you just copied.
Run your application and you've down the following:
Host
Client
Service
Consumed
That is how to consume a WCF Data Service the article that has even more detail is here:
Hopefully that helps.

Using WCF REST services with Unity on IIS

I am trying to use dependency injection with WCF REST (WebGet) and am having trouble understanding where I would use Unity to build my object to host the web service.
I have seen many examples all over the web, but they seem to all be hosting the service in a console app or Windows service.
Currently my config file looks like this:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="Services.MyRestService">
<endpoint address="http://localhost:8732/api" binding="webHttpBinding" contract="Shared.Services.IMyRestService"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior>
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
Currently the way it works is using the built in WCF service host in Visual Studio. However, I'd like to run this in IIS and use Unity to configure my container. Now I am using "bastard injection" to get the job done, but would like to use Unity to supply the data provider implementation, etc.
My question is, what configuration changes do I need to make to host this in IIS and also where do I configure the container and let IIS know about it.
There are no SVC files as this is a WCF Service Library.
Thanks in advance!
The "normal" way to do this would be to implement a custom IInstanceProvider WCF extension point, and add it through configuration. I've only done this with regular SOAP endpoints, but I think it would work the same for WebAPI.
Couple links that might help:
IInstanceProvider (MSDN)
Extending WCF Using IInstanceProvider
IInstanceProvider (MSDN Blog)
Integrating Unity with WCF
The 2nd link covers some of the XML configuration stuff for adding a custom IInstanceProvider to the behavior.
With WCF REST you would use WebServiceFactory and WebServiceHost as your base classes.

WCF Error - Could not find default endpoint element that references contract 'UserService.UserService'

Any ideas how to fix this?
UserService.UserServiceClient userServiceClient = new UserServiceClient();
userServiceClient.GetUsersCompleted += new EventHandler<GetUsersCompletedEventArgs>(userServiceClient_GetUsersCompleted);
userServiceClient.GetUsersAsync(searchString);
.
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_UserService"
maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:52185/UserService.svc"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_UserService"
contract="UserService.UserService"
name="BasicHttpBinding_UserService" />
</client>
<behaviors>
<serviceBehaviors>
<behavior name="Shell.Silverlight.Web.Service3Behavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<services>
<service behaviorConfiguration="Shell.Silverlight.Web.Service3Behavior"
name="Shell.Silverlight.Web.Service3">
<endpoint address=""
binding="basicHttpBinding"
contract="Shell.Silverlight.Web.Service3" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
Could not find default endpoint element that references contract 'UserService.UserService' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.
Resolved!
I didn't mention that this was a Silverlight application. I had the wcf reference in a DLL which had it's own "ServiceReferences.ClientConfig" file. I moved the contents of the DLL's ServiceReferences.ClientConfig to the main silverlight project and it worked.
I had a run in with the same problem. My application was also a Silverlight application and the service was being called from a class library with a custom UserControl that was being used in it.
The solution is simple. Copy the endpoint definitions from the config file (e.g. ServiceReferences.ClientConfig) of the class library to the config file of the silverlight application. I know you'd expect it to work without having to do this, but apparently someone in Redmond had a vacation that day.
You can also set these values programatically in the class library, this will avoid unnecessary movement of the config files across the library.
The example code for simple BasciHttpBinding is -
BasicHttpBinding basicHttpbinding = new BasicHttpBinding(BasicHttpSecurityMode.None);
basicHttpbinding.Name = "BasicHttpBinding_YourName";
basicHttpbinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
basicHttpbinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
EndpointAddress endpointAddress = new EndpointAddress("http://<Your machine>/Service1/Service1.svc");
Service1Client proxyClient = new Service1Client(basicHttpbinding,endpointAddress);
Just in case anyone hits the same problem whilst using WPF (rather than WCF or Silverlight):
I had this error, when connecting to a Web Service. When my code was in the "main" WPF Application solution, no problem, it worked perfectly. But when I moved the code to the more sensible DAL-layer solution, it would throw the exception.
Could not find default endpoint element that references contract 'MyWebService.MyServiceSoap' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.
As has been stated by "Sprite" in this thread, you need to manually copy the tag.
For WPF apps, this means copying the tag from the app.config in my DAL solution to the app.config in the main WPF Application solution.
I ran into the same issue, for whatever reason Visual Studio did not update the web config when I first added the service. I found that updating the Service Reference also fixed this issue.
Steps:
Navigate to the Service Reference Folder
Expand it
Right Click and Select update Service Reference
Observe web Config be updated
Change the web.config of WCF service as "endpoint address="" binding="basicHttpBinding"..." (previously binding="wsHttpBinding")After build the app, in "ServiceReferences.ClientConfig" ""configuration> has the value. Then it will work fine.
Rename the output.config produced by svcutil.exe to app.config.
it worked for me.
Do you have an Interface that your "UserService" class implements.
Your endpoints should specify an interface for the contract attribute:
contract="UserService.IUserService"
Not sure if this is an issue.
Endpoint and binding both have the same name
Not sure if it's really a problem, but I see you have the same name for your binding configuration ().
I usually try to call my endpoints something like "UserServiceBasicHttp" or something similar (the "Binding" really doesn't have anything to do here), and I try to call my binding configurations something with "....Configuration", e.g. "UserServiceDefaultBinding", to avoid any potential name clashes.
Marc
Had to add the service in the calling App.config file to have it work. Make sure that you but it after all . This seemed to work for me.
This problem occures when you use your service via other application.If application has config file just add your service config information to this file.
In my situation there wasn't any config file so I use this technique and it worked fine.Just store url address in application,read it and using BasicHttpBinding() method send it to service application as parameter.This is simple demonstration how I did it:
Configuration config = new Configuration(dataRowSet[0]["ServiceUrl"].ToString());
var remoteAddress = new System.ServiceModel.EndpointAddress(config.Url);
SimpleService.PayPointSoapClient client =
new SimpleService.PayPointSoapClient(new System.ServiceModel.BasicHttpBinding(),
remoteAddress);
SimpleService.AccountcredResponse response = client.AccountCred(request);
For those who work with AX 2012 AIF services and try to call there C# or VB project inside AX (x++) and suffer from such errors of "could not find default endpoint"... or "no contract found" ...
go back to your visual studio (c#) project and add these lines before defining your service client, then deploy the project and restart AX client and retry:
Note, the example is for NetTcp adapter, you could easily use any other adapter instead according to your need.
Uri Address = new Uri("net.tcp://your-server:Port>/DynamicsAx/Services/your-port-name");
NetTcpBinding Binding = new NetTcpBinding();
EndpointAddress EndPointAddr = new EndpointAddress(Address);
SalesOrderServiceClient Client = new SalesOrderServiceClient(Binding, EndPointAddr);
In case if you are using WPF application using PRISM framework then configuration should exist in your start up project (i.e. in the project where your bootstrapper resides.)
In short just remove it from the class library and put into a start up project.

Categories

Resources