The WCF REST Contrib library adds functionality to the current WCF REST implementation.
PM> Install-Package wcfrestcontrib
Thanks to the following contributors:
Thanks to JetBrains for providing OSS licenses for R# and dotTrace!
The WCF REST Contrib library adds additional functionality to the current WCF REST implementation.
License: MIT License
Per the discussion thread at http://wcfrestcontrib.codeplex.com/Thread/View.aspx?ThreadId=68350:
It would be great if the WebDispatchFormatter configuration could be applied at the endpoint or service, instead of just at the service.
In our project we would like to use WcfRestContrib, but we have decided to use Digest authentication. Do you have any word on that, or should we build it and supply a patch?
From Web.xml
<behavior name="Rest"> ... <formatter mimeTypes="application/json" type="WcfRestContrib.ServiceModel.Dispatcher.Formatters.DataContractJson, WcfRestContrib"/>
My service returns serialized JSON result without problems, but there is a problem with deserialization from JSON.
It's configured with
[ServiceConfiguration("Rest", true)] [WebDispatchFormatterConfiguration("application/json")] [WebDispatchFormatterMimeType( typeof(WcfRestContrib.ServiceModel.Dispatcher.Formatters.DataContractJson), "application/json")]
and the method is
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "order")] [WebDispatchFormatter] [OperationContract] [OperationAuthentication] OrderExternal CreateOrder(OrderCreateRequest createOrderRequest);
I'm testing it using a Java client where I'm sending a
String message = "{\"CurrencyCode\":\"SEK\", \"OrderLines\": []}";
I tested and this string is serializable into OrderCreateRequest, so it's valid JSON.
I'm sending this message as Content-Type "application/json".
However, deserialization fails with DeserializationException:
The request body could not be deserialized. Encountered unexpected character '%'.
And this is due to code in
public object Deserialize(WebFormatterDeserializationContext context, Type type) { if (context.ContentFormat != WebFormatterDeserializationContext.DeserializationFormat.Xml) throw new InvalidDataException("Data must be in xml format."); var serializer = new DataContractJsonSerializer(type); return serializer.ReadObject(context.XmlReader); }
This code looks fishy. XmlReader here is {None} in execution. And ReadObject here raises exception in question.
I suspect this is a WcfRestContrib issue or an application config problem, since I don't know what else could be the reason for this. Sending request encoded as application/json to POST in HTTP seems to be valid and my string is validly encoded and can be deserialized into proper JSON. However, somehow I cannot see that WCF/WcfRestContrib is fetching that string properly and there is no more stack trace here so that I can see any more details.
Help or comment would be appreciated.
I wanted to use our implementation of JsonNet in WcfRestContrib for the standard content type application/json and create a new content type called application/dotnetxml for the standard DataContractSerializer (not using POX). I ran into problems because WCF by default intercept the application/json content type and sets the WebContentFormat to Xml (or it may have been Json, but the point is that it should be Binary). I also had the same issue when using a custom content type for DataContractSerializer, since the default for WCF for an unknown content type is Binary, but for the DataContractSerializer it must be Xml.
This then causes the DataContract implementations to fail because the message comes in with the wrong content/data type.
My fix was to create a ContentTypeMapper and wire that into the bindings under the WebMessageEncoder. That worked well, then I had to determine which content format each formatter needed. I extended the IWebFormatter in WcfRestContrib to have a property that returns the required content type, so long everything was good.
The main issue was how to get that data into my custom ContentTypeMapper. I couldn't find any live references during initialization that would let me do it. I ended up doing an ugly hack with a static dictionary in the mapper. I'm not too happy about that solution, it works, but ugly. Because of that I haven't created a public patch for that. If anyone has the same issue I'm happy to email the patch, but I don't think this should go into the main trunk in its current state.
jQuery likes to append the charset onto it's content-type.
example: Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Seems that the system should be able to parse that out appropriately and not roll down to a PoxDataContract instead of the FormUrlEncoded
When running my project on my DiscountAsp.Net Windows 2008 Server w/ IIS7 and .Net 4.0 I'm not able to access the current username w/ a call to OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Name. Trying to do so results in a System.NullReferenceException: Object reference not set to an instance of an object exception. I've checked my Web.config and other settings time and time again and haven't found any reasonable explanation for this as I know OpeartionContextExtensions was meant to fix this problem.
Interestingly enough I tried the hack in which you decode and parse the Authentication Headers to get the username/password and this worked sometimes, but other times lead to the exact same error using the exact same request in fiddler.
One thing I found especially interesting was that once it did get the username correctly using this method, requests afterward also seamed to work. However, Session State was disabled in IIS Manager the whole time. I need to access the username 100% of the time however so even this is not good enough.
There is a need to submit a raw friendly message that is not string.formattable. To do so, please add another constructor:
public WebException(HttpStatusCode status, string friendyMessage) :
base(friendyMessage)
{
Status = status;
}
Therefore, if there are no parameters, the string.format() method is never called and the friendly message can contain any combination of braces such as JavaScript code.
The current logic in WcfRestContrib.ServiceModel.ServiceHostBaseExtensions.LoadBehaviors seems geared towards allowing behaviors specified delcaritively in [ServiceConfiguration] to override server config values, however WcfRestContrib.ServiceModel.Web.WebServiceHost.OnOpening (which processess the ServiceConfig attributes) completely ignores the ServiceConfigurationAttribute if there is an existing service element.
See lines 45 and 58 of WebServiceHost.cpp.
If I set a breakpoint on those lines, and reassign the instruction pointer to call LoadBinding or LoadBehaviors (even though this.HasServiceElement() == true), everything works as I originally expected (per http://wcfrestcontrib.codeplex.com/Wiki/View.aspx?title=Declarative%20Binding%20%26%20Behavior%20Overview&referringTitle=Home)
As a developer I would like to return something other than a 401 error when a Basic Authentication request fails so my user isn't prompted with a log in dialog via the browser.
I get the following error when trying to install.
C:/Ruby192/lib/ruby/1.9.1/rubygems/remote_fetcher.rb:300:in `open_uri_or_path':
bad response Forbidden 403 (http://production.s3.rubygems.org/quick/Marshal.4.8/
wcfrestcontrib-1.0.5.0.gemspec.rz) (Gem::RemoteFetcher::FetchError)
Looks like the gem isn't available?
The POXXmlReader is passing some requests down to the XmlReader/XmlDictionaryReader and intercept others with its XmlNodeReader through the property Reader. I ran into an issue where the POX reader couldn't deal with base64 binary data, even if its Reader could. The framework calls ReadObject and when the stream contains base64 data it throws a NotSupported exception. But if I check the XmlNodeReader that the POX is using for most of the methods, then it works. But ReadContentAsBase64 is not intercepted and is then passed down to XmlDictionaryReader, which cannot handle base64 binary.
I've attached a patch that implements a base64 handler for the POX reader.
One of our servers was recently upgraded to .NET 4.5 and my .NET 4.0 WcfRestContrib app broke when processing a POST request with a simple text body. The error coming out is:
Error.Message=System.Xml.XmlException%3a+%27Text%27+is+an+invalid+XmlNodeType.
%0d%0a+++at+System.Xml.XmlReader.ReadEndElement()
%0d%0a+++at+WcfRestContrib.ServiceModel.Dispatcher.WebDispatchFormatter.Deserialize(Message+message%2c+WebFormatterFactory+formatterFactory%2c+Object%5b%5d%26+parameters%2c+RequestMessagePartDescription%5b%5d+requestParameters%2c+String+contentType)+in+d%3a%5cTeamCity%5cBuildAgent%5cwork%5cdac2ac50c21c000f%5csrc%5cWcfRestContrib%5cServiceModel%5cDispatcher%5cWebDispatchFormatter.cs%3aline+149
%0d%0a+++at+WcfRestContrib.ServiceModel.Dispatcher.WebDispatchFormatter.DeserializeRequest(Message+message%2c+Object%5b%5d+parameters)+in+d%3a%5cTeamCity%5cBuildAgent%5cwork%5cdac2ac50c21c000f%5csrc%5cWcfRestContrib%5cServiceModel%5cDispatcher%5cWebDispatchFormatter.cs%3aline+73%
0d%0a+++at+System.ServiceModel.Dispatcher.DispatchOperationRuntime.DeserializeInputs(MessageRpc%26+rpc)
%0d%0a+++at+System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc%26+rpc)
%0d%0a+++at+System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc%26+rpc)
%0d%0a+++at+System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc%26+rpc)
%0d%0a+++at+System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean+isOperationContextSet)&Error.Status=500
The error is in BInaryBodyReader.cs, at line 15 and the date it's trying to deserialise is a byte stream corresponding to the request body which, for what it's worth, is:
source=TweetDeck&screen%5Fname=d%5Froberts&text=Testing%20Zeitgeist
At this point I'm a bit stuck on how to proceed as I've been unable to find this sort of thing mentioned in any of the .NET 4.5 breaking changes. Any ideas or solutions would be very welcome. Many thanks,
Nick North
PS I am using the WcfRestContrib 1.7.10.0 NuGet package.
PPS I have just realised something else that may be important. I have my own reader for application/x-www-form-encoded data (which this request has as its content type), which is declared with the attributes on the service below. It looks as though my reader is not being invoked.
// Set this as the default MIME type because WCFRestContrib tries to match the entire Content-Type, which includes the boundary string for multipart/form-data
// so cannot be matched, as that is random. We happen to know that anything that is not application/x-www-form-urlencoded is multipart/form-data, so the trick
// works.
[WebDispatchFormatterConfiguration("multipart/form-data")]
[WebDispatchFormatterMimeType(typeof(FormEncodedFormatter), "application/x-www-form-urlencoded")]
In order to support both SOAP and REST with a single ServiceContract (interface) that is shared between both .svc files, the WebDispatchFormatter attribute needs to be added to the methods inside the ServiceContract... The issue with this is that the SOAP .svc doesn't make use of the WebServiceHostFactory, which causes WebDispatchFormatterBehavior to throw a ConfigurationErrorsException.
In order to allow this, I suggest adding a constructor parameter to WebDispatchFormatterAttribute named "allowDormant", which will instruct WebDispatchFormatterAttribute to instruct WebDispatchFormatterBehavior that it is ok if the behavior is unable to apply the dispatch behavior.
I have attached a zip file containing the proposed change. The files in the zip are based on Change Set 25579.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.