I've implemented a customized QueryStringConverter class and hooked it up using a customized WebHttpBehavior subclass. When I make a service call, it hits my breakpoint in the CanConvert override (and I return true for this parameter), but it never calls my ConvertStringToValue override, and ends up just passing null to the service call... why is ConvertStringToValue never called and how can I fix it?
This is not possible.
Microsoft were so sloppy with the implementation of this functionality that they merely newed up the standard QueryStringConverter instread of using the one configured in the configuration file.
There are no work arounds that actually work. The second one in the bug report doesn't actually work at all.
The short answer is that you cannot.
See the bug here: http://connect.microsoft.com/VisualStudio/feedback/details/616486/bug-with-getquerystringconverter-not-being-called-by-webservicehost#tabs
It is still broken in framework 4.0.
My guess is that it's not important - so perhaps take the time to increase the counts on the bug.
Regards
Craig.
I know it is quite old question. For any one who looking for some answer, you should be able to add the TypeConverter to your class which can convert type to and from string representation
http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.querystringconverter.aspx
Types that have a TypeConverterAttribute that can convert the type to
and from a string representation.
Do some thing like this:
In contract file
[OperationContract]
[WebGet(UriTemplate = "/TabelasAuxiliares?requestex={requestex}", ResponseFormat = WebMessageFormat.Xml)]
CadastrodeEscolasResponse TabelasAuxiliares(string requestex);
In the Service file
public CadastrodeEscolasResponse TabelasAuxiliares(string requestex)
{
XmlSerializer serializer = new XmlSerializer(typeof(CadastrodeEscolasRequest));
StringReader rdr = new StringReader(requestex);
CadastrodeEscolasRequest request = (CadastrodeEscolasRequest)serializer.Deserialize(rdr);
}
Conslusion:
Call the service by sending Xml format data to a string parameter. Then convert the xml to the required class object. This way you can avoid creating QueryStringConvertor which is quite cumbersome. Hope this will help! This help is for all and not just for this post.
Related
I'm currently learning the API for Autofac, and I'm trying to get my head around what seems to me like a very common use case.
I have a class (for this simple example 'MasterOfPuppets') that has a dependency it receives via constructor injection ('NamedPuppet'), this dependency needs a value to be built with (string name):
public class MasterOfPuppets : IMasterOfPuppets
{
IPuppet _puppet;
public MasterOfPuppets(IPuppet puppet)
{
_puppet = puppet;
}
}
public class NamedPuppet : IPuppet
{
string _name;
public NamedPuppet(string name)
{
_name = name;
}
}
I register both classes with their interfaces, and than I want to resolve IMasterOfPuppets, with a string that will be injected into the instance of 'NamedPuppet'.
I attempted to do it in the following way:
IMasterOfPuppets master = bs.container.Resolve<IMasterOfPuppets>(new NamedParameter("name", "boby"));
This ends with a runtime error, so I guess Autofac only attempts to inject it to the 'MasterOfPuppets'.
So my question is, how can I resolve 'IMasterOfPuppets' only and pass parameter arguments to it's dependency, in the most elegant fashion?
Do other ioc containers have better solutions for it?
Autofac doesn't support passing parameters to a parent/consumer object and having those parameters trickle down into child objects.
Generally I'd say requiring the consumer to know about what's behind the interfaces of its dependencies is bad design. Let me explain:
From your design, you have two interfaces: IMasterOfPuppets and IPuppet. In the example, you only have one type of IPuppet - NamedPuppet. Keeping in mind that the point of even having the interface is to separate the interface from the implementation, you might also have this in your system:
public class ConfigurablePuppet : IPuppet
{
private string _name;
public ConfigurablePuppet(string name)
{
this._name = ConfigurationManager.AppSettings[name];
}
}
Two things to note there.
First, you have a different implementation of IPuppet that should work in place of any other IPuppet when used with the IMasterOfPuppets consumer. The IMasterOfPuppets implementation should never know that the implementation of IPuppet changed... and the thing consuming IMasterOfPuppets should be even further removed.
Second, both the example NamedPuppet and the new ConfigurablePuppet take a string parameter with the same name, but it means something different to the backing implementation. So if your consuming code is doing what you show in the example - passing in a parameter that's intended to be the name of the thing - then you probably have an interface design problem. See: Liskov substitution principle.
Point being, given that the IMasterOfPuppets implementation needs an IPuppet passed in, it shouldn't care how the IPuppet was constructed to begin with or what is actually backing the IPuppet. Once it knows, you're breaking the separation of interface and implementation, which means you may as well do away with the interface and just pass in NamedPuppet objects all the time.
As far as passing parameters, Autofac does have parameter support.
The recommended and most common type of parameter passing is during registration because at that time you can set things up at the container level and you're not using service location (which is generally considered an anti-pattern).
If you need to pass parameters during resolution Autofac also supports that. However, when passing during resolution, it's more service-locator-ish and not so great becausee, again, it implies the consumer knows about what it's consuming.
You can do some fancy things with lambda expression registrations if you want to wire up the parameter to come from a known source, like configuration.
builder.Register(c => {
var name = ConfigurationManager.AppSettings["name"];
return new NamedPuppet(name);
}).As<IPuppet>();
You can also do some fancy things using the Func<T> implicit relationship in the consumer:
public class MasterOfPuppets : IMasterOfPuppets
{
IPuppet _puppet;
public MasterOfPuppets(Func<string, IPuppet> puppetFactory)
{
_puppet = puppetFactory("name");
}
}
Doing that is the equivalent of using a TypedParameter of type string during the resolution. But, as you can see, that comes from the direct consumer of IPuppet and not something that trickles down through the stack of all resolutions.
Finally, you can also use Autofac modules to do some interesting cross-cutting things the way you see in the log4net integration module example. Using a technique like this allows you to insert a specific parameter globally through all resolutions, but it doesn't necessarily provide for the ability to pass the parameter at runtime - you'd have to put the source of the parameter inside the module.
Point being Autofac supports parameters but not what you're trying to do. I would strongly recommend redesigning the way you're doing things so you don't actually have the need to do what you're doing, or so that you can address it in one of the above noted ways.
Hopefully that should get you going in the right direction.
I have been trying to create an ISessionFactory that has a list of filters as a property (so it can be specified in the XML configuration) and enables each of the filters whenever OpenSession() is called.
Unfortunately, I have been stymied at every turn. I've subclassed LocalSessionFactoryObject and SimpleDelegatingSessionFactory, mixed-and-matched every way I can think of, but there's always some syntax or run-time error that keeps it from working.
Can anyone give me an example of how to do this?
Thanks in advance.
[Update]
I've been asked to provide some code to illustrate my issue. I don't think that's really relevant to the question I'm asking, but I can elaborate:
I figured that to make sure the filters are enables whenever a new session is opened I'd have to have my own OpenSession method. It seemed the best way to do this was to subclass DelegatingSessionFactory, add the filter-list property and a method like this
public new ISession OpenSession()
{
var rtn = base.OpenSession();
foreach (var filter in filters)
rtn.EnableFilter(filter);
return rtn;
}
When I had Spring construct this as my ISessionFactory object, though, I got runtime errors about not having an exception translator. So, I figured I'm better off also subclassing LocalSessionFactoryObject and having it create an ISessionFactory of my new type with the filter list, rather than the default type. To do this I tried to override NewSessionFactory, but then I got a runtime error about not having a DbProvider defined, and when I tried to copy the code that handles this from LocalSessionFactoryObject I got a bunch of syntax errors because of the scope of some members...
In short, something that seemed like it should be simple -- and that in fact I rather expected many to have done before me -- turned in a coding safari. That's why I'm looking for someone who's already done it, or who at least understands the framework better than I do.
But do the filters need to be active always? If that is the case, then you should instead be using Where restrictions on the entity and/or collections.
I currently have all of my WCF connections defined in code and I'm trying to shoehorn protobuff-net serialization in with little success. None of my contracts are marked with the knowntype attribute as we have a base message with a payload (it would be dozens of knowntypes). We figure out the knowntypes we have and cache them in a class derived from DataContractSerializerOperationBehavior. Then in the overridden CreateSerializer function I pass the cached known types into the DataContractSerializer as follows
public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList<Type> knownTypes)
{
new DataContractSerializer(type, name, ns, m_Known ?? knownTypes, 0x7FFF, ...)
}
Is there some way to pass a list of known types to the protobuf-net serializer. I realize protobuf-net isn't meant to mirror the serializers for WCF, but it would be nice if they followed the pattern for allowing overriding the knowntypes list. Thanks for any help.
However I don't have the option to treat the Protobuf-net serializer this way (I looked at the ProtoOperationBehavior). Is there anyway to not have known types specified in the
In "v2", the available subtypes can be defined (against a RuntimeTypeModel) on the fly at runtime via .AddSubType(...) (in fact, all the attributes now only serve as a default configuration for the type-model, which can be configured any which way).
However, I should stress that v2 is currently in beta, and as noted in the blog the WCF hooks are currently not included in the beta, purely while I finish validation etc. However, I expect that with your setup as shown in the question it should be trivial (it will merely be a case of passing the model into the XmlObjectSerializer implementation provided).
Is DataContract attribute is deprecated in ASP.NET 4.0 WCF ? I can see only DataContractFormat attribute.
I can't apply DataContractFormat attribute over struct.
example
[DataContractFormat]
public struct Contact
{
public string firstName;
public string lastName;
}
It throws an error saying that DataContractFormat artribute can only be used on class, interface and methods.
No, the .NET 4 still contains the DataContractAttribute:
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute%28v=VS.100%29.aspx
and it should be able to be applied to class or struct.
You have to add a reference to the System.Runtime.Serialization assembly (right click References, add ref...)
DataContract is not deprecated - where the heck did you get that idea from?
DataCOntractFORMAT is something totally different. I suggest you please read the documentation ;) Helps a lot. Will also explain what DataContractFormat is for.
http://msdn.microsoft.com/en-us/library/system.servicemodel.datacontractformatattribute.aspx
As you can see in the example this attribute goes on the class/interface that defines the SERVICE CONTRACT. It controls how for that service data serializaton is (guess what) formatted.
I am fairly new to WCF and just have a question on how to correctly get MessageContract inheritance working. A simplified version of my setup is as follows - a "base" message type, and then another "test" message which inherits from it.
[MessageContract]
public abstract class BaseMessage
{ }
[MessageContract]
public class TestMessage : BaseMessage
{ }
I then have an asynchronous OperationContract on a ServiceContract defined as:
[OperationContract(AsyncPattern = true)]
IAsyncResult BeginFindRequest(BaseMessage request, AsyncCallback callback, object asyncState);
The problem that I am getting is when calling the BeginFindRequest method, and passing in a TestMessage instance for the request parameter, the WCF framework is deserialising the TestMessage instance to BaseMessage on the service/server side. As this is defined as an abstract class, it results in the following error:
"The message cannot be deserialized
into MessageContract type BaseMessage
since it does not have a default
(parameterless) constructor."
From the limited information that I can find on MessageContract inheritance, it seems that it should just work.
So my question is - what am I missing in order to get this to work; or should I perhaps rather define a seperate OperationContract on the ServiceContract specifically for that type - the downside being that I could end up with many additional OperationContracts?
In the end I found this blog post which hit the nail on the head -
Unfortunately the way that contracts
are expressed in WCF makes is very
easy to forget what their purpose is:
to define the messages send to the
operation and being sent back from the
operation. In reality you have to
think “how would I express this data
in XML?”. XML doesn’t support
inheritance so whatever you put in the
contract is going to have to have some
way of mapping to XML. The data
contracts used to define the messages
are simply a .NET typed convenience
for generating the XML for the data
you want to pass – if you view them
any other way you are destined for a
world of pain. So think about the data
you want to pass, not how it may
happen to be represented in your
business layer and design your
DataContracts accordingly.
http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,a3775eb1-b441-43ad-b9f1-e4aaba404235.aspx
So I will be refactoring to provide an additional method with an explicit contract type. This will also allow me to clean up the service implementation by removing all the type checking.
Thanks for the assistance.
OK, first question is: why are you really using Message contracts? Do you really have a need for that??
Typically, message contracts are only ever used when you need to tightly control the layout of your SOAP message, e.g. to satisfy a legacy system you need to call which requires specific headers and such.
A "normal" WCF call should hardly ever need to use a message contract.
You define your service calls (the methods on your service) using [ServiceContract], and the data structures being passed around as [DataContract]. If you have a DataContract, you have more options as to how to deal with inheritance / polymorphism in your service (more than with the message contract construct).
Marc
Is that possible to change BaseMessage so that it is concrete class with parameterless constructor?
The error message tells that there is no way to initialize the object of type BaseMessage because it is abstract.
The error simply wants you to have a default empty contructor that it can use. However, I agree with marc_s; in the projects I've worked on I've rarely used message contract, the only case I can remember was as part of a file transfer service where file chunks were passed in messasges.
Try decorating your [ServiceContract] with the KnownType attribute. Since TestMessage is not 'visible' from a public operation, this helps the plumbing know how to treat it when it sees it.
If this should allow the [DataContract] to be serialized as a TestMessage your still likely to need to handle multiple messages differently via 'is a' or some other casting.
Well I had declared this default (parameterless) constructor for sure, but that was not still working fine for me, for me the issue was, the access modifier was protected while it should be public:
public constructor() { }
^^^^