.NET Core 2.0 - Http client accept header not recognized - asp.net-core

httpClient.DefaultRequestHeaders.Add("Accept", "application/vnd.pagseguro.com.br.v3+json;charset=ISO-8859-1");
Is there any bug related to how you should add a accept header to a request?
This is a request for a specific payment gateway in Brazil (pagseguro). I've already posted in their forums but none of the members seems to be using .NET Core there yet.
Message I get: Accept header is mandatory

You should try something like:
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/vnd.pagseguro.com.br.v3+json"));
httpClient.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("charset=ISO-8859-1"));
DefaultRequestHeaders.Accept is a collection of string type, where you can add your header to accept using the new instance of MediaTypeWithQualityHeaderValue.

Related

How to get the base64 signature encoding for a WCF request

I have a WCF client proxy and am using the following binding element to sign the request to a third party Java web service:
Dim asec As TransportSecurityBindingElement = SecurityBindingElement.CreateCertificateOverTransportBindingElement()
asec.EnableUnsecuredResponse = True
asec.SetKeyDerivation(False)
asec.AllowInsecureTransport = True
asec.IncludeTimestamp = True
However, I'm told there is a validation error on the service side:
Signature validation failed: Invalid encoding type (only base64 is
supported) for token:uuid-168b7c90-2d6a-4928-9979-94cb84443d3b-1
So I'm assuming I need to set something (probably the signature?) to base64 encoding. How can I do this?
To answer the question in your answer:
Though I don't know why this works, or what it means.
SecurityBindingElement.CreateCertificateOverTransportBindingElement() initializes the MessageSecurityVersion of the binding to its defaults, which is:
WS-Security 1.1, WS-Trust of February 2005, WS-SecureConversation of February 2005 and WS-SecurityPolicy 1.1.
With the overload you're now calling, you're specifying this:
Basic Security Profile 1.0 based on WS-Security 1.0, WS-Trust of February 2005, WS-SecureConversation of February 2005 and WS-SecurityPolicy 1.1 security specifications.
To determine what EncodingType WCF actually emits, you'll have to either put an HTTP monitor in between (e.g. Fiddler) or let .NET output trace information to log the message being sent. You can also access or request the server logs to see why the server thinks the message is invalid.
I suspect however, given certain web searches on the actual error message, that the Java server complains about your WCF client omitting the EncodingType=...#Base64Binary on the wsse:BinarySecurityToken. According to the spec, that is the only allowed value (or a custom one if both parties agree on it) and it's not marked as optional.
After changing the MessageSecurityVersion to WS-sec 1.0 as also explained here (which is easy to find - once you know what you're looking for), I guess WCF explicitly outputs the EncodingType attribute, causing the service to accept the message.
Setting the MessageSecurityVersion to WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10 seemed to solve the problem:
Dim asec As TransportSecurityBindingElement = SecurityBindingElement.CreateCertificateOverTransportBindingElement(ServiceModel.MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10)
Though I don't know why this works, or what it means.

Jaxrs multipart

I'm trying to perform a request to a jaxrs service which has media type set to multipart/form-data. This request contains a list of entities(xml) and an image(png, binary). I have created the request as described in this thread by BalusC.
The request seems ok after inspecting it in wireshark, except for the ip header checksum being wrong.(says something about "may be caused by IP checksum offload".)
My big issue here is how to handle the multipart request on the service side. I do not wish to include any libraries from apache.cxf, resteasy or anything of the sort. All I want to rely on is the jaxrs api.
The two parts in the request have names deliveries and signature, where the signature is a png image file sent as binary. The list of deliveries should be parsed from an xml(the entity has the xmlrootelement annotation and such, so this part works separately). I've attempted with this way of reading the different parts, but this was really a longshot;
#PUT
#Path("signOff")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public void signOffDeliveries(#FormParam("deliveries") List<Delivery> deliveries, #FormParam("signature")File signature) {
//do something with the signature(image) and the list of deliveries.
}
This does off course not work, and it gives me a 404 http status code if I run the request on Websphere, and a 415 when I run the request towards an embedded openejb (in our integration test framework). If I remove the FormParam annotations the request succeeds.
How can I read the different parts of the multipart request using only the jaxrs api?
EDIT
Ok, so I canged the PUT to POST, and added an #Encoding annotation to the params as so:
#POST
#Path("signOff")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public void signOffDeliveries(
#Encoded #FormParam("deliveries") String deliveries,
#Encoded #FormParam("signature") File signature) {
}
Now I get the xml as a text string, but I am not able to automatically unmarshal it to a list of deliveries even though the Content-Type of this part of the payload is set to application/xml. The other problem is that the file I receive has length==0, and I am not able to read any bytes from it.
Am I missing an essential point here?
Indeed I find it hard to understand why the JAX-RS spec doesn't standardize a support for this (I've just created https://java.net/jira/browse/JAX_RS_SPEC-413 to address this).
However it is nevertheless possible to support multi-part forms in an implementation independent fashion. Either you write your own MessageBodyReader for MultiPart form or you use a library like Apache Clerezza jaxrs.utils which provide a MultiPartBody object which respective MessageBodyReader. This library has no implementation specification dependency so your application will run on any jax-rs implementation.
For an example on how Clerezza jaxrs.utils is used see line 105 in http://svn.apache.org/viewvc/stanbol/trunk/development/archetypes/stateless-webmodule/src/main/resources/archetype-resources/src/main/java/MultiEnhancer.java?revision=1465777&view=markup. If you're not using OSGi (with white-board registration of resources) you will have to add to org.apache.clerezza.jaxrs.utils.form.MultiPartFormMessageBodyReader to your Application.
I have implemented this in Glassfish 4 without coupling with Jersey. #See this post for details
I do not wish to include any libraries from apache.cxf, resteasy or anything of the sort. All I want to rely on is the jaxrs api
You can't "rely on" the API, since it contains only interfaces. Classes that implement that interfaces come from RESTeasy, or Jersey, or CXF.
and a 415 when I run the request towards an embedded openejb
415 means "Method not supported", which happens when you send GET request to a PUT-expecting resource.
I would recommend to use POST instead of PUT in this case. I suspect that #FormParam is not suitable to work with PUT, in your particular case.

WCF Data Services version 5.0 and Json

I want my OData service to support Json serialization, I read about a WCF Data Service toolkit which add this behaviour to the V2 version. After I read WCF Data Service released a new version of WCF Data Service 5.0, I need to know how to do it.
I add the $Format=json and I get all the time this attribute isn't supported.
Any suggestion .
Thanks in advance ...
The usual way to request JSON is to use Accept header (basically following HTTP, if the client wants a certain representation of the response, it should ask for it in the Accept header).
So if you send Accept: application/json;odata=verbose, you will get the Verbose JSON response.
WCF Data Services currently doesn't implement the $format query option. But you can add it "on top". There are several ways to do this (just search the web). One of them is for example here: http://archive.msdn.microsoft.com/DataServicesJSONP

Implementing versioning a RESTful API with WCF or ASP.Net Web Api

Assume i've read a lot about versioning a restful api, and I decided to not version the the service through the uri, but using mediatypes (format and schema in the request accept header):
What would be the best way to implement a wcf service or a web api service to serve requests defining the requested resource in the uri, the format (eg. application/json) and the schema/version (eg player-v2) in the accept header?
WCF allows me to route based on the uri, but not based on headers. So I cannot route properly.
Web Api allows me to define custom mediatypeformatters, routing for the requested format, but not the schema (eg. return type PlayerV1 or PlayerV2).
I would like to implement a service(either with WCF or Web Api) which, for this request (Pseudo code):
api.myservice.com/players/123 Accept format=application/json; schema=player-v1
returns a PlayerV1 entity, in json format
and for this request:
api.myservice.com/players/123 Accept format=application/json; schema=player-v2
returns a PlayerV2 entity, in json format.
Any tips on how to implement this?
EDIT: To clarify why I want to use content negotiation to deal with versions, see here: REST API Design: Put the “Type” in “Content-Type”.
What you are bringing here does not look to me as versioning but it is is more of content negotiation. Accept header expresses wishes of the client on the format of the resource. Server should grant the wishes or return 406. So if we need more of a concept of Contract (although Web API unline RPC does not define one) then using resource is more solid.
The best practices for versioning have yet to be discussed fully but most REST enthusiast believe using the version in the URL is the way to go (e.g. http://server/api/1.0.3/...). This also makes more sense to me since in your approach using content negotiation server has to keep backward compatibility and I can only imagine the code at the server will get more and more complex. With using URL approach, you can make a clean break: old clients can happily use previous while new clients can enjoy the benefits of new API.
UPDATE
OK, now the question has changed to "Implementing content-negotiation in a RESTful AP".
Type 1: Controller-oblivious
Basically, if content negotiation involves only the format of the resource, implementing or using the right media type formatter is enough. For example, if content negotiation involves returning JSON or XML. In these cases, controller is oblivious to content negotiations.
Type 2: Controller-aware
Controller needs to be aware of the request negotiation. In this case, parameters from the request needs to be extracted from the request and passed in as parameter. For example, let's imagine this action on a controller:
public Player Get(string schemaVersion)
{
...
}
In this case, I would use classic MVC style value providers (See Brad Wilson's post on ValueProviders - this is on MVC but Web API's value provider looks similar):
public Player Get([ValueProvider(typeof(RequestHeadersSchemaValueProviderFactory))]string schemaVersion)
{
...
}

Restlet basic HTTP Authentication : Help required

I am running Restful web service on 8182 port using restlet framework. I am trying to authenticate user to hit the service. i.g.
I have a query string like this http://localhost:8182/api/service/customers/?key="XXXXXXXXX"
My doubts are:
How to get value of parameter key in Resource class/Application class, so i can authenticate user upon key through my custom database.
I don't have any client code for my restful service, since i want to invoke all call from browser itself. so please tell me,how to send post data from browser itself. since i want to use post/put method to add new customer data.
I am using restlet framework 1.1.
Thanks in advance.
Karunjay Anand
You can use:
getRequest().getResourceRef().getQueryAsForm()
This will return a Form instance from which you can get the value of your query parameters (getFirstValue("key"), for example).
As Bruno pointed out, you can obtain a Form instance to access the request's query parameters:
Form form = getRequest().getResourceRef().getQueryAsForm();
for (Parameter p : form) {
System.out.println("Name: " + p.getName());
System.out.println("Value: " + p.getValue());
}
If you want to use the POST method from the browser itself, I would recommend you use one of the following add-on/extensions:
Firefox - REST Client
Google Chrome - Simple REST Client