Error comsuming WCF service metadata? - c#

We have a WCF webservice selfhosted in a windows service application.
It works fine to generate and call a simple method from both a .NET winform application and SoapUI(after changin to correct IP and set authentication header).
The problem is that when trying to add the WSDL to a BizTalk we get "Error consuming WCF service metadata. Object reference not set to an instance of an object". and nothing more.
I have search internet and there is some that have hade the same problem and they are talking about namespace problems. I have checked the generated .NET winform proxy but there is no warnings or anything that might suggest problems with namespaces? I notice in the WSDL that some namespaces tags do only have a "" value but not sure if that might be a problem.
Is there any way to get more information from Biztalk about where the error might be in this massive WSDL?
When browsing the WSDL from another computer it will use localhost(instead of the IP och DNS) so I have to use WSDL singelfile to genereate the proxy and I have to manually change the URL to the specific IP in the client to get it working. This should however not be the problem.
Here is how the service is started :
_serviceHost = new ServiceHost(typeof(T), new Uri(baseEndpoint.Address));
ServiceThrottlingBehavior throttleBehavior = new ServiceThrottlingBehavior
{
MaxConcurrentCalls = 200,
MaxConcurrentInstances = 2147483647,
MaxConcurrentSessions = 2000,
};
_serviceHost.Description.Behaviors.Add(throttleBehavior);
_serviceHost.Description.Behaviors.Add(smb.HttpGetEnabled = true);
foreach (var endpointDescription in _additionalServiceEndpoints)
{
var endpoint = new ServiceEndpoint(ContractDescription, endpointDescription.Binding, new EndpointAddress(endpointDescription.Address));
_endpointBehaviors.ForEach(c => endpoint.EndpointBehaviors.Add(c));
_serviceHost.AddServiceEndpoint(endpoint);
}
_serviceBehaviors.ForEach(c => _serviceHost.Description.Behaviors.Add(c));
ServiceAuthorizationBehavior serviceAuthorizationBehavior = _serviceHost.Description.Behaviors.Find<ServiceAuthorizationBehavior>();
if (serviceAuthorizationBehavior == null)
{
_serviceHost.Description.Behaviors.Add(new ServiceAuthorizationBehavior());
}
if (_authorizationPolicies.Count > 0)
{
serviceAuthorizationBehavior.ExternalAuthorizationPolicies = new ReadOnlyCollection<IAuthorizationPolicy>(_authorizationPolicies.ToArray());
serviceAuthorizationBehavior.PrincipalPermissionMode = PrincipalPermissionMode.Custom;
serviceAuthorizationBehavior.ServiceAuthorizationManager = new CustomServiceAuthorizationManager();
}
((ServiceBehaviorAttribute)_serviceHost.Description.Behaviors[typeof(ServiceBehaviorAttribute)]).MaxItemsInObjectGraph = 2147483647;
((ServiceBehaviorAttribute)_serviceHost.Description.Behaviors[typeof(ServiceBehaviorAttribute)]).IncludeExceptionDetailInFaults = true;
_serviceHost.Open();

Have you tried the solution which is described in this forum thread: https://social.msdn.microsoft.com/Forums/en-US/19105b96-5ec4-40f1-972b-2e04f889061f/biztalk-2010-error-consuming-wcf-service-metadata-object-reference-not-set-to-an-instance-of-an?forum=biztalkgeneral
It points to a blog post located here: https://blogs.msdn.microsoft.com/kerreybpi/2009/02/05/biztalk-error-wcf-service-consuming-wizard/
The solution might be (from the link above):
1, Generate WSDL and XSD files by using svcutil tool
svcutil.exe /t:metadata http://yourservice
2, Verify nodes in WSDL file, make sure the node has a target namespace define. It doesn't matter what attribute value you use, maybe just looks like http://any.
3, Select Metadata Files(WSDL and XSD) as the source
4, Everything should be fine.

I just had the same error when trying to consume .svc?singleWsdl. When I consume as just .svc into the "Add Generated Items" wizard then it works.

Related

Accessing SOAP Webservice Problems

at the moment Iam working as a working student at a Software Company and I got the task to setup a client who works with a webservice from a third party (only have a wsdl-, xsd file and user certificate).
I read a lot about Webservices in the last time and I did a lot of tutorials, but I did not manage to connect to the Server and make a simple test request.
I have a Windowsform Application an added a Service reference to the project via the physical path of the wsdl document. From this the generated proxy classes.
The wsdl and xsd file you can find here [https://www.dropbox.com/sh/qgopygt9gtbhwq6/AADHp8k1ktfNrzMVKCjQ0EsPa?dl=0][1]
EndpointAddress ea = new EndpointAddress("https://212.62.77.106:9443/hapwebservices/secure_routed/dms");
DMSServiceClient client = new DMSServiceClient(new BasicHttpsBinding(), ea);
X509Certificate2 cert = new X509Certificate2(#"C:\Users\myName\Desktop\DMS-test-2016.p12", "privateKey");
client.ClientCredentials.ClientCertificate.Certificate = cert;
Header header = new Header();
header.InputTime = DateTime.Now;
header.SystemId ="TheSystemID";
header.OrganisationId = "TheOrganisationID";
header.Password = "Password";
header.OrganisationName = "Oraganisation";
header.InterfaceVersion="3.0";
header.DMSVersion = "1";
header.DMSName = "DMSNAME";
DateTime datetime = DateTime.Now;
client.test(header, ref datetime);
Above you see my Code to invoke the test Method. But I alway get the exception that the Server Certificate is probably not configured correctly with HTTP.SYS. Another Reason is a mismatch from Client and Server.
Can you help me with this issue? Have I set up the proxy classes correctly?
Many thanks in advance!
Regards Lars

Edit WCF message before it is sent to server

We recently had to upgrade our Win 8.1 store app to Win 10. Part of that change was modifying our NetTcpBindings to instead be BasicHttpBindings for file uploads since UWP does not currently support NetTcpBindings. Our issue is that when the client calls the UploadFileMethod on the proxy class, we intercept the message before it is sent to the server so we can apply headers that are used later as follows:
public async Task UploadFileAsync(RemoteFileInfo request)
{
using (new OperationContextScope(this.InnerChannel))
{
string nameSpace = #"http://tempuri.org";
OperationContext.Current.OutgoingMessageHeaders.Add(MessageHeader.CreateHeader("FileName", nameSpace, request.FileName));
OperationContext.Current.OutgoingMessageHeaders.Add(MessageHeader.CreateHeader("Length", nameSpace,
request.Length));
await Channel.UploadFileAsync(request);
}
}
This used to work fine when we were using NetTcpBinding but since we switched to BasicHttpBinding that code is now throwing an exception on the line:
await Channel.UploadFileAsync(request);
With the exception reading:
This message cannot support the operation because it has been written.
After reading up on this exception it appears that we cannot mess with the request object at all before it is sent to the server when using BasicHttpBinding. If that is the case, how can we add OutgoingMessageHeaders to the message using properties of the request itself?
Edit: The proxy class is created as follows:
var imageProxy = new RTMImageServiceProxy(globalContext.Win10UploadBinding,
globalContext.ImageEndpointAddress);
Where Win10UploadBinding is configured as so:
BasicHttpBinding win10BasicBinding = new BasicHttpBinding();
win10BasicBinding.Security.Mode = BasicHttpSecurityMode.None;
win10BasicBinding.TransferMode = TransferMode.Streamed;
win10BasicBinding.SendTimeout = new TimeSpan(0, 0, 2, 0);
win10BasicBinding.MaxReceivedMessageSize = 2147483647;
this.win10UploadBinding = win10BasicBinding;
and globalContext is just a static class I used to store commonly-used variables.
Apparently it turns out that once written cannot be altered so create a copy with adjusted headers. Equivalent issue was brought up here.
Anyway, I encourage you to create custom message inspector: class deriving IClientMessageInspector, as far as client is concerned. It provides separation between method being invoced and headers being adjusted.

How can I test if the DataContractSerializer was effectively replaced by XmlProtoSerializer?

I have a series of self-hosted WCF services (using netTcpBinding) that I want to enhance by using the fantastic protobuf-net serializer.
I configured both the client and the service endpoints with the custom behavior extensions as instructed in the documentation of the ProtoEndpointBehavior class (see here). My tests ran fine from the very first try, however, I'm very skeptical of WCF-stuff running fine at the very first try ;)
Is there a simple way in which I can assert that the default DataContractSerializer was replaced by the XmlProtoSerializer?
I would really favor a test that can be also coded as part of a unit test. I wouldn't like the protobuf-net library to be inadvertently disabled by careless tampering of the .config file.
If you call your service in wcf test client, you will see < proto/> tag in the body of response
If you configure your client to use proto behaviour and call service with "inadvertently disabled protobuf", your answer will be null because of different serializers. You can check it in your test
var address = new EndpointAddress( url );
var binding = GetBinding( address.Uri );
var factory = new ChannelFactory<TService>( binding, address );
factory.Endpoint.EndpointBehaviors.Add( CreateProtobufEndpointBehavior() );
var client = factory.CreateChannel();
var answer = client.GetSomeInt();
AssertAnswerIsNotNull(answer);

How to increase the file size limit in WCF console application

I've having a very simple WCF service (a console application for file upload). I keep getting error (400) bad request. It works when I upload small files (4kb) but failing for 700kb.
From the readings I've done from stack overflow and other, I'll have to increase the MaxReceivedMessageSize. This was implemented using a custom class and overriding the OnOpening method but it still didn't work.
I'm testing with a console application using the webclient
outputBytes = webClient.UploadData(baseUrl + "/uploads/2." + filenameOnly, File.ReadAllBytes(filename));
Also, I'm using the WebServiceHost as in
var uri = new Uri("http://localhost:8000");
var svc = new WebServiceHost(typeof (UploadService), uri);
How do I solve this issue?
PS: Application does not have a config file so I'll looking at how to set this in code. If not and a config file is needed, then what should be the content.
Notes:
I found this link Bad Request Error 400 - WCF Client where it was explained that those properties are only valid for soap based services. He suggested updating the web.config. Since this is a console application, I'm wondering how this can be done'
regards.
You can set the maximumreceivedmessage programatically like this:
var binding = new wsHttpBinding(); // or whatever binding you are using
binding.MaxReceivedMessageSize = Int32.MaxValue;
var wcfClient = new WCFServiceTestClient(binding, strServiceURL);
Hopefully this will be enough to solve your problem, but you might also want to consider chopping up the file into bits (batching) before sending it to the server. Sending very large chunks of data can incurr a huge memory penalty as the client has to serialize the entire thing up front before sending it to the server (and then the same to deserialize it on the server side).
Edit: Based on your additional comment (below), the code on the application hosting the service might look something like this:
WebServiceHost webServiceHost = new WebServiceHost(typeof(UploadService), uri);
WebHttpBinding binding = new WebHttpBinding();
binding.MaxReceivedMessageSize = Int32.MaxValue;
webServiceHost.AddServiceEndpoint(typeof(IUploadService), binding, "WebServiceHost");
webServiceHost.Open();
Did you have a look at the documentation?
It covers both code and configuration.

How do I get a value from an XML web service in C#?

In C#, if I need to open an HTTP connection, download XML and get one value from the result, how would I do that?
For consistency, imagine the webservice is at www.webservice.com and that if you pass it the POST argument fXML=1 it gives you back
<xml><somekey>somevalue</somekey></xml>
I'd like it to spit out "somevalue".
I think it will be useful to read this first:
Creating and Consuming a Web Service (in .NET)
This is a series of tutorials of how web services are used in .NET, including how XML input is used (deserialization).
I use this code and it works great:
System.Xml.XmlDocument xd = new System.Xml.XmlDocument;
xd.Load("http://www.webservice.com/webservice?fXML=1");
string xPath = "/xml/somekey";
// this node's inner text contains "somevalue"
return xd.SelectSingleNode(xPath).InnerText;
EDIT: I just realized you're talking about a webservice and not just plain XML. In your Visual Studio Solution, try right clicking on References in Solution Explorer and choose "Add a Web Reference". A dialog will appear asking for a URL, you can just paste it in: "http://www.webservice.com/webservice.asmx". VS will autogenerate all the helpers you need. Then you can just call:
com.webservice.www.WebService ws = new com.webservice.www.WebService();
// this assumes your web method takes in the fXML as an integer attribute
return ws.SomeWebMethod(1);
You can use something like that:
var client = new WebClient();
var response = client.UploadValues("www.webservice.com", "POST", new NameValueCollection {{"fXML", "1"}});
using (var reader = new StringReader(Encoding.UTF8.GetString(response)))
{
var xml = XElement.Load(reader);
var value = xml.Element("somekey").Value;
Console.WriteLine("Some value: " + value);
}
Note I didn't have a chance to test this code, but it should work :)
It may also be worth adding that if you need to specifically use POST rather than SOAP then you can configure the web service to receive POST calls:
Check out the page on MSDN:
Configuration Options for XML Web Services Created Using ASP.NET

Categories

Resources