WCF routing using XPath : invalid qualified name exception - wcf

I am trying to impelemnt content based routing using XPath in wcf.
I have create class library which contains service contract and data contract as following.
[ServiceContract(Namespace = "http://orders/")]
public interface IService5
{
[OperationContract]
string GetData(int value);
}
[DataContract]
public class Quantity
{
[DataMember]
public int value1 { get; set; }
}
I created one service as follows:
public class Service5 : IService5
{
public string GetData(int value)
{
return string.Format("You entered in service 5: {0}", value);
}
}
And I am trying to implement routing based on 'value'
In app.config (inside router project) i hav added following lines for namespace and XPath filter
<namespaceTable>
<add prefix="cc" namespace="http:orders/Quantity/"/>
</namespaceTable>
<filters>
<filter name="All" filterType="XPath" filterData="cc://value1 > 500 " />
But whenever i run the code i get an exception for ' cc://value1 > 500 ' as invalid qualified name exception.
How can i resolve this ?

There are multiple things wrong here:
The class Quantity on which you appear to want to apply the filter does not feature in your service contract at all, so will be entirely absent in the XML for filtering purposes.
The namespace in your router config starts http:orders, when the service contract namespace starts http://orders.
The namespace in your router config contains /Quantity, when the service contract namespace does not.
The filter xpath cc://value1 is not a valid xpath
---

Hey The problem is in the line
filter name="All" filterType="XPath" filterData="cc://value1 > 500 "
It should be
<filter name="All" filterType="XPath" filterData="//cc:value1 > 500 " />
observe cc:// in ur code.
This will solve ur problem

Related

how to set attributes in soap format WCF

how to set attributes for soap message:
for example my soap messg look like following
<doPaymentResult xmlns:a="http://schemas.datacontract.org/2004/07/MemoService" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:errors i:nil="true"/>
<a:messages>
<a:MessageEntity>
<a:codeField>Payment Request Successful</a:codeField>
<a:textField i:nil="true" xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
</a:MessageEntity>
</a:messages>
<a:requestTrackCode>20130430T125904R14646</a:requestTrackCode>
<a:status i:nil="true"/>
</doPaymentResult>
</doPaymentResponse>
but i need a soap message which take attributes not elements
like following
<doPaymentResult xmlns:a="http://schemas.datacontract.org/2004/07/MemoService" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:errors i:nil="true"/>
<a:messages>
<a:MessageEntity codeField="Payment Request Successful">
some text here
</a:MessageEntity>
</a:messages>
<a:requestTrackCode>20130430T125904R14646</a:requestTrackCode>
<a:status i:nil="true"/>
</doPaymentResult>
</doPaymentResponse>
I am using datacontract in class.
It’s a common problem – you want to return an object from a WCF service as XML, but you either want, or need, to deliver some or all of the property values as XML Attributes instead of XML Elements; but you can’t because the DataContractSerializer doesn’t support attributes (you’re most likely to have seen this StackOverflow QA if you’ve done a web search). Most likely you’ve then migrated all your WCF service code to using the XmlSerializer (with all the XmlElement/XmlAttribute/XmlType attributes et al) – and you’ve cursed loudly.
Well, I’m here to rescue you, because it is possible – and the answer to the problem is actually inferred from the MSDN article entitled ‘Types supported by the Data Contract Serializer’.
The example I’m going to give is purely for illustration purposes only. I don’t have a lot of time, so work with me!
•Create a new Asp.Net WCF service application, you can use Cassini as your web server (probably easier – otherwise you might have to enable Asp.Net compatibility mode).
•Open the web.config and delete the element that was created for the new service.
•The interface and implementation model for this example is overkill. Move the [ServiceContract] and [OperationContract] declarations from the interface that was created for you new service to the class that was also created. Delete the interface.
•Open the .svc markup file and add the following at the end: Factory="System.ServiceModel.Activation.WebServiceHostFactory" – this enables the zero-configuration WCF model for this service (we’re going to create a RESTful service).
•Paste the following class declarations into your svc codebehind:
public interface IExampleData
{
string Description { get; set; }
string Name { get; set; }
int ID { get; set; }
}
public class ExampleData : IExampleData
{
public string Description { get; set; }
public string Name { get; set; }
public int ID { get; set; }
}
public class ExampleDataAttributed : ExampleData, IXmlSerializable
{
#region IXmlSerializable Members
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
//implement if remote callers are going to pass your object in
}
public void WriteXml(System.Xml.XmlWriter writer)
{
writer.WriteAttributeString("id", ID.ToString());
writer.WriteAttributeString("name", Name);
//we'll keep the description as an element as it could be long.
writer.WriteElementString("description", Description);
}
#endregion
}
Just to demonstrate the point, the class that will be part-serialized to attributes simply derives from one that will be serialized as normal.
•Now add the following two methods to your service class:
[OperationContract]
[WebGet(UriTemplate = "/test1")]
public ExampleData Test1()
{
return new ExampleData() { ID = 1,
Name = "Element-centric",
Description =
"The contents of this item are entirely serialized to elements - as normal" };
}
[OperationContract]
[WebGet(UriTemplate = "/test2")]
public ExampleDataAttributed Test2()
{
return new ExampleData_Attributed() { ID = 2,
Name = "Mixed",
Description =
"Everything except this description will be serialized to attributes" };
}
Cover, and bake for 40 minutes (that is – Build it).
If you left your service as Service1.svc, then run it and open up IE and browse to http://localhost:[port of cassini]/test1
The result should look something like this:
<JSLabs.ExampleData
xmlns="http://schemas.datacontract.org/2004/07/ExampleNamespace"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Description>
The contents of this item are entirely serialized to elements - as normal
</Description>
<ID>
1
</ID>
<Name>
Element-centric
</Name>
</JSLabs.ExampleData>
Now browse to http://localhost:[port of cassini]/test2
<JSLabs.ExampleDataAttributed id="2" name="Mixed"
xmlns="http://schemas.datacontract.org/2004/07/JobServe.Labs.Web">
<description>Everything except this description will be
serialized to attributes</description>
</JSLabs.ExampleDataAttributed>
It’s made a little less impressive by that nasty ‘orrible “xmlns=” attribute that the WCF data contract serializer automatically puts on the type – but, as you can see, the ‘ID’ and ‘Name’ properties have indeed been pushed out as attributes!
We could have made both methods return IExampleData and then used the KnownType attribute on that interface in order to get it to support either (according to what the code of the methods returned).
To support deserializing an object from the attributes, all you have to do is to implement the IXmlSerializable.ReadXml method.
Finally, as the aforementioned MSDN article says about the supported types – you should also be able to use XmlElement/XmlNode types as a way of representing XML directly – the DataContractSerializer, like in this case, take the short route and simply gets the Xml.
This also shouldn’t affect JSON formatting if you’re dual-outputting objects for either XML or JSON clients.
Check the source of this article

WCF Update Service Reference Error

I'm desesperated, I'm trying to update an existing service reference to a WCF service (sharing types) and I can't. I've tryied all what I've found on Google (social.msdn, stackoverflow, ...) but I haven't found the solution to my problem.
I've have a ServiceContract and I add a new Operation like the code below:
[ServiceContract]
public partial interface IServiceDTO : IGenericServiceDTO<EntityDTO>
{
// Some OperationContracts working like
[OperationContract]
EntityDTO[] Method(int field);
// NewMethod
[OperationContract]
OtherEntityDTO[] NewMethod(int field);
}
[DataContract]
public class EntityDTO {
// Some properties working
}
[DataContract]
public class OtherEntityDTO {
// Some properties working
[DataMember]
YetAnotherEntity NewProperty {get;set;}
}
When I try to update the service reference it throws me the follwing error:
Attempting to download metadata from 'http://localhost:65499/Services/Acciones/ProcesoServiceDTO.svc' using WS-Metadata Exchange or DISCO.
Error: Cannot import wsdl:portType
Detail: An exception was thrown while running a WSDL import extension: System.ServiceModel.Description.DataContractSerializerMessageContractImporter
Error: Referenced type 'mpm.seg.ServiceModel.DTO.DataContracts.Acciones.ProcesoDTO, mpm.seg.ServiceModel.DTO.DataContracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' with data contract name 'ProcesoDTO' in namespace 'http://schemas.datacontract.org/2004/07/mpm.seg.ServiceModel.DTO.DataContracts.Acciones' cannot be used since it does not match imported DataContract.
Need to exclude this type from referenced types.XPath to Error Source: //wsdl:definitions[#targetNamespace='http://tempuri.org/']/wsdl:portType[#name='IProcesoServiceDTO']
First of all, I don't understand exactly the sentence "...cannot be used since it does not match imported DataContract." How the svcutil is trying to match referenced type to imported DataContract? I've referenced the project that have the referenced types on the client project, cause server and client are in the same solution, but I've tried to separate them and reference exactly the same dll too.
Also, when I try, for example, the following situation it works (write "NewProperty" of the "OtherEntityDTO to EntityDTO"), and I don't understand the difference:
[ServiceContract]
public partial interface IServiceDTO : IGenericServiceDTO<EntityDTO>
{
// Some OperationContracts working like
[OperationContract]
EntityDTO[] Method(int field);
// NewMethod
[OperationContract]
OtherEntityDTO[] NewMethod(int field);
}
[DataContract]
public class EntityDTO {
// Some properties working
[DataMember]
YetAnotherEntity NewProperty {get;set;}
}
[DataContract]
public class OtherEntityDTO {
// Some properties working
}
Please, help me and thanks a lot in advance.
Sorry, but after I've posted the question I've found the problem and it was a reported bug (http://blogs.msdn.com/b/distributedservices/archive/2010/02/04/wcf-client-issue-with-reuse-types-from-referenced-assemblies.aspx?wa=wsignin1.0). Another developer had added this attribute (IsReference=true) on a parent class and I didn't know. Now I must to workaround this bug, but that's another battle.
Anyway, I don't understand why sometimes work and sometimes not...
Thanks.
I had a similar error, but my issue seemed to be different.
I had a readonly property and I kept getting that error. When I changed it to a normal property and added a set (that did nothing), the contract worked fine.

Can't change wcf contract's method return values

I'm building a WCF service, I have written the contract in the IService file and Implemented it in the Service file, The problem shows up when I try to change any of the return values of the methods I have declared and that's because they are being saved behind in the code in CustomersService namespace specifically in the CustomersServiceClient class which is locked and can't be accessed to change.
This is the code I have in the ICustomersService file:
[ServiceContract]
public interface ICustomersService
{
[OperationContract]
CustomerDetails GetCustomerDetails(string customerid);
[OperationContract]
bool VerifyId(string customerid);
}
and the code in the CustomersService file:
public CustomerDetails GetCustomerDetails(string customerid)
{
....
}
public bool VerifyId(string customerid)
{
...
}
and in the CustomerService1 namespace I have this code which has been generated and locked, so any attemp to modify the methods I have in the IService is failling because it's locked here and can't be changed!
public class CustomersServiceClient : ClientBase<ICustomersService>, ICustomersService
{
public CustomersServiceClient();
public CustomersServiceClient(string endpointConfigurationName);
public CustomersServiceClient(Binding binding, EndpointAddress remoteAddress);
public CustomersServiceClient(string endpointConfigurationName, EndpointAddress remoteAddress);
public CustomersServiceClient(string endpointConfigurationName, string remoteAddress);
public CustomerDetails GetCustomerDetails(string customerid);
public bool VerifyId(string customerid);
}
this is serious problem for me I hope you find me some answers.
Web services are slightly more complicated than just referenced assemblies. Proxy classes code is not updated automatically if you change service interface. You need to update it manually every time you changed the contract.
Try this:
Client Project -> Service References
Select your Reference -> Right mouse click
Update Service Reference
WCF also can reuse your contract types if you reference that assembly. In that case changes in data contract will be seen in client immediately. You may find implementation steps in that answer:
How to use a custom type object at the client

WCF - Exposing parameterized constructor

I have a WCF DataContract called RecipientDto defined as:
[DataContract]
public class RecipientDto
{
[DataMember]
public string Name
{
get;
private set;
}
[DataMember]
public string EmailAddress
{
get;
private set;
}
public RecipientDto(string name, string emailAddress)
{
Name = name;
EmailAddress = emailAddress;
//Initialize other property here
}
}
I want to have constructor of RecipientDto being exposed to the client as it involve some basic initialization of other properties (not shown here).
Please guide how can I achieve this.
Thank you!
You cannot achieve that unless you share assembly with your DTOs between client and server. Metadata (WSDL + XSD) can describe only data transferred by DTO. They cannot describe any logic defined in DTO on service side.
What you could do is the create a second source file for the RecipientDto class, that contains a second declaration of the class with the "partial" keyword. Add your constructor to it and include that file in your client project using Visual Studio's "Add Link" functionality available on the "Add existing item" dialog. If you only need that constructor on the client then just define that second source file directly in the client project.

WCF DataContract ToString function

Can you override the ToString function in a WCF DataContrat? Right now I have:
[DataContract]
public class Keyword
{
public int ID { get; set; }
public string Name { get; set; }
public override string ToString()
{
return Name;
}
}
But it doesn't seem to work. Anyway to get this working?
I realize this is old but wanted to provide an answer since I just created a sample app for a coworker that used this idea. All of this work can be done on the consumer/test client side.
If you look at the code on the consumer/test client and, more specifically, the classes that are generated as part of the service reference, you will see the [DataContract] type you are interested in. In order to do this you should make sure that 'Show All Files' is selected. Drill down to the 'Reference.cs' class.
This is the top of my test class from Reference.cs:
namespace WebApplication1.UCCTestSvcRef {
using System.Runtime.Serialization;
using System;
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="UCCRecord", Namespace="http://schemas.datacontract.org/2004/07/UCCTest")]
[System.SerializableAttribute()]
public partial class UCCRecord : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged {
The important bits that you will need to use are the namespace and the partial class. To make use of these you simply have to create a new class in your test client of the same type, in the same namespace, and override the ToString() method.
Here is an example of how to do that from the newly created UCCRecord.cs file on the consumer/test client.
namespace WebApplication1.UCCTestSvcRef
{
public partial class UCCRecord
{
public override string ToString()
{
return "Key: " + Key.ToString() + ", Time: " + Timestamp.ToString("d") + ", Value: " + Value;
}
}
}
Note that I can only reference Key and Timestamp and Value because they are [DataMember] values for the [DataContract].
This is relatively simple if you know what you are looking for. If anything here is not clear, please let me know and I will attempt to clarify.
Thanks
Where do you want to be able to invoke ToString()? Methods are not part of the DataContract so they won't be available when you create the proxy for the client.
Of course, nothing is stopping you from coding that method in the client's proxy yourself.
Remember too that if you own both the server and the client, that often you can use a shared library for data contracts rather than generating a client proxy. If you do that, then you can have the same method on both the server and client as they're exactly the same type.