I have a pretty simple WCF service set up with a method similar to:
[OperationContract]
[WebGet(UriTemplate = "/GetById/{id}")]
ResponseSingle<BinderViewModel> GetById(string id);
When I try and hit it with a GUID like...
http://localhost/services/myservicename.svc/GetById/5c3f04d7-f96e-4acd-847b-6da5937e
It returns a 500 and an exception stating:
Length cannot be less than zero. Parameter name: length
If I remove the UriTemplate and instead hit it as:
http://localhost/services/myservicename.svc/GetById?id=5c3f04d7-f96e-4acd-847b-6da5937e
It works fine.
I've done a bit of reading and it looks like the request will fall over when it grows > a certain length.
Wondering if anyone else has been bitten by this previously and if so had any luck resolving it?
Cheers,
Tim
[WebGet(UriTemplate = "/GetById/{id}")]
Should be:
[WebGet(UriTemplate = "/GetById?id={id}"]
Adding more information (as I was confused for a second), /Action/{variable} is for the path of the service. I.e., /GetBy/ID or /GetBy/Name
Whereas, the method is expecting a value to complete processing of the service, so that will have to be a query in the syntax ?CaseSenstiveMethodParameterName={queryParameter}
MSDN URL Template Help
Related
I am sending a POST request to a WCF Web service using fiddler, and the service responds with HTTP 400: The request has an invalid header name.
The post request looks like this:
User-Agent: Fiddler
Host: localhost:49392
Content-Type: application/json
Content-Length: 0
{ "clientFirstName" : "John"}
My endpoint is defined as follows:
[OperationContract]
[System.ServiceModel.Web.WebInvoke
(Method = "POST",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = System.ServiceModel.Web.WebMessageFormat.Json,
BodyStyle = System.ServiceModel.Web.WebMessageBodyStyle.Wrapped,
UriTemplate = "MakeReservation")]
String MakeReservation(Stream reservationStream);
MORE
First of all, the JSON was in the wrong pane. I moved it to the Request Body pane.
I changed the prototype of the function to take a String instead of Stream as the input parameter. The service now accepts my call and returns 200, but in the debugger I see that the input parameter String is null. When I change it back to Stream, I get 400 again.
YET MORE
Enable tracing gives me at trace file with the following message:
Incoming message for operation 'MakeReservation' (contract 'ITalLimoService' with namespace
'http://tempuri.org/') contains an unrecognized http body format value 'Json'. The expected body
format value is 'Raw'. This can be because a WebContentTypeMapper has not been configured on the
binding. See the documentation of WebContentTypeMapper for more details.
As noted int the WebInvoke definitiuon, both the RequestFormat and ResponseFormat are set to WebMessageFormate.Json. Why is IIS complaining about this?
I don't know why this works, but for some reason removing the following line from the fiddler Composer did the trick:
Content-Type: application/json
And that is that. I would give points for an explanation.
I know this post is old. But very strange, when I removed the header "application/json" it worked.
Has it got to do with server setup?
The request could not be understood by the server due to deformed syntax. The client SHOULD NOT repeat the request without modifications.If request to your server with data that is in the correct format, but its bad data. eg: a Posted String value to an API endpoint that expected a String value; but, the value of the string contained data that was something else.
The syntax of the request entity is correct (thus a 400 (Bad Request) status code is inappropriate) but was unable to process the contained instructions. For example, this error condition may occur if an XML request body contains syntactically correct but semantically wrong XML instructions.
I've read this example http://msdn.microsoft.com/en-us/library/ee476510.aspx about dynamic responses in wcf.
The sample on the bottom fit my goal pretty well. This is what i did:
[OperationContract]
[WebGet(UriTemplate = "/salaries({queryString})")]
Message GetSalaryByQuery(string queryString);
and my GetSalaryByQuery-Method:
public Message GetSalaryByQuery(string querystring)
{
if (WebOperationContext.Current.IncomingRequest.Accept == "application/json")
return WebOperationContext.Current.CreateJsonResponse<Result>(Salary.GetSalaryByQueryJson(querystring));
else
return WebOperationContext.Current.CreateAtom10Response(Salary.GetSalaryByQuery(querystring));
}
It is pretty similiar to the example i found.
But its not working however. It says that there is another parameter besides the message. I googled the message-class and it seems to me that its not possible to add an parameter to a message-response.
Is there a way to pass a parameter with the request and get a response with a message object?
Is there another way to get the dynamic response?
Thanks in advance.
I got it to work. I just deleted the Metadata-Enpoint and the behavior. My Webservice provides metadata on its own and therefore doesnt need to have the mex-Metadata defined.
I have a wcf service defined like this:
[OperationContract]
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json)]
public CreateOrderResponse CreateOrder(CreateOrderRequest request)
The request parameter is populated fine, but inside my method a what to access HttpContext.Current.Request.InputStream to get the raw post body but the InputStream is empty, InputStream.Lenght is 0.
My question is why is Request.InputStream empty when the request parameter is populated fine from the post request?
You need to use the CreateOrderRequest instance and it's associated properties.
As far as I know, and I may be wrong, the Inputstream would always be null as it has been processed prior to being passed to your WCF method. See this link for more information Capturing raw HTTP POST Data during Exception
I am in the process of writing a WCF webapi application and have a need to check whether an email address is taken or not. This needs to be a query the client-side code can do before attempting a PUT.
So, what I'm trying to do is use HEAD in conjunction with HTTP status codes. I am a little unsure how to go about doing that as it's a simple yes/no response which is required. So, I've used HttpResponseExceptions to return the relevant status code.
[WebInvoke(Method = "HEAD", UriTemplate = "{email}")]
[RequireAuthorisation]
public void IsEmailAddressTaken(string email)
{
if (!Regex.IsMatch(email, Regexes.EmailPattern))
{
throw new RestValidationFailureException("email", "invalid email address");
}
if (_repository.IsEmailAddressTaken(email))
{
throw new HttpResponseException(HttpStatusCode.OK);
}
throw new HttpResponseException(HttpStatusCode.NoContent);
}
This just doesn't "smell" right to me.
am I going about doing this kind of yes/no operation the right way?
My suggestion is to return a HttpResponseMessage instead of throwing exceptions.
Is your RestValidationFailureException being handled anywhere? If not, it will result in a 500 status code, which does not seem adequate.
I think it would be ok to just return OK for "exists" and 404 for "does not exist"
I am building a REST service on WCF, and one of the methods I am writing is GetProfile, which will return the profile for a given username. The username will include the user's domain, and so will have the following format: "DOMAIN\username".
I therefore have a service called Profiles.svc, which has the following endpoint set up:
[OperationContract]
[WebGet(UriTemplate = "/{username}", ResponseFormat = WebMessageFormat.Xml)]
IRestResponse GetProfile(String username);
However, when I attempt to visit the service at http://server/profiles.svc/DOMAIN%5cusername (%5c is the urlencoded form of a backslash) I get the following error:
Server error in '/' Application
HTTP Error 400 - Bad Request
This occurs even when there is no code actually defined in my implementation of GetProfile, so I believe the error is being thrown at the point WCF attempts to bind the URI to a method.
Are there some settings I need to add to my web service configuration in order to allow backslashes to be added to URLs in a REST WCF service? Or are backslashes simply not allowed?
I suspect that they are simply not allowed in that part of the url. They are fine in the query string as long as they are encoded. As a general rule i wouldn't put anything in the path part of the url that is invalid in filename (i.e. ?).
Perhaps you could use a different character to deliminate th domain from the username.
You could also seperate the username into domainname and username and use the normal path deliminator '/'. I'm not familar with the this enough to know if this is how you do it for sure, but this would be my best guess.
[OperationContract]
[WebGet(UriTemplate = "/{domainName}/{username}", ResponseFormat = WebMessageFormat.Xml)]
IRestResponse GetProfile(String domainName, String username);