I would like to send a string (JSON formatted) to my webservice instead using a DTO.
var client = new JsonServiceClient(absoluteUrl);
client.Post<T>(absoluteUrl, data);
But, after to do change my data (DTO object) to a JSON string, I'm getting a ServiceStack Exception: Internal Server Error. Looks like the ServiceStack Post/Send method changes my JSON request.
Is it possible or is there any way to avoid it? Someone else had the same issue?
UPDATE 1: I'm using this approach because of the OAuth authentication. I'm generating a HMAC by request.
Thanks.
You can use HTTP Utils to send raw JSON, e.g:
var response = absoluteUrl.PostJsonToUrl(data)
.FromJson<T>();
ServiceStack's .NET Service Clients provide Typed API's to send Typed Request DTO's, it's not meant for POST'ing raw strings but I've just added support for sending raw string, byte[] and Stream in this commit so now you can send raw data with:
var requestPath = request.ToPostUrl();
string json = request.ToJson();
var response = client.Post<GetCustomerResponse>(requestPath, json);
byte[] bytes = json.ToUtf8Bytes();
response = client.Post<GetCustomerResponse>(requestPath, bytes);
Stream ms = new MemoryStream(bytes);
response = client.Post<GetCustomerResponse>(requestPath, ms);
This change is available from v4.0.43+ that's now available on MyGet.
Sharing Cookies with HttpWebRequest
To have different HttpWebRequests share the same "Session" you just need to share the clients Cookies, e.g. after authenticating with a JsonServiceClient you can share the cookies with HTTP Utils by assigning it's CookieContainer, e.g:
var response = absoluteUrl.PostJsonToUrl(data,
requestFilter: req => req.CookieContainer = client.CookieContainer)
.FromJson<T>();
Related
I'm using the client and I need to call a service using authsecret parameter.
If I ad this param to the base url it give me a serialization error.
String baseUrl = AppConfig.GetAppApiUrl();
var client = new JsonServiceClient(baseUrl.AddQueryParam("authsecret","secretz123!"));
var c = client.Send(new ComuneRequest { Id = "A001" });
Using Fiddler I discovered that the request that the client generate is incorrect:
POST
http://192.168.0.63:820/?authsecret=secretz123%21/json/reply/ComuneRequest
So, what I have to do to make the client create a request in a correct format?
It needs to be sent as a Request Parameter (i.e. QueryString or FormData) which you can do using HTTP Utils with:
var url = baseUrl.CombineWith(requestDto.ToUrl()).AddQueryParam("authsecret", secret);
var res = url.GetJsonFromUrl().FromJson<MyResponse>();
Otherwise since AuthSecret is not a property on your Request DTO you wont be able to send it as a Request Parameter in the Request Body, but you should be able to send the param in the Request Headers with:
var client = new JsonServiceClient(baseUrl) {
RequestFilter = req => req.Headers[HttpHeaders.XParamOverridePrefix+"authsecret"] = secret
};
I have an Azure Function that I have configured that listens for incoming messages to an Azure Service Bus. I can receive the messages without a problem. But when I try to route the request onto another service for processing, I am getting an error stating that the POST data is empty.
public static void Run(BrokeredMessage message, TraceWriter log)
{
log.Info($"C# ServiceBus queue trigger function processed message: {message.MessageId}");
if (message != null)
{
//MessageObjectEntity is a custom object
Common.Entities.MessageObjectEntity messageObject = message?.GetBody<Common.Entities.MessageObjectEntity>();
string msgType = messageObject?.MessageType;
var msgContent = messageObject?.MessageContent; // MessageContent is of type object to allow any object to be sent
using (var client = new HttpClient())
{
string url = $"http://mycompany.azurewebsites.net/api/routingtasks?formname={msgType}";
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(subscriber, token);
HttpContent content = new StringContent((string)msgContent, Encoding.UTF8, "application/json");
var response = client.PostAsync(new Uri(url), content); // at this point content is valid
// I am getting a BadRequest returned here as the target service has not received the POST data
// that was sent in via the content variable
}
log.Info("Completing message.");
}
It appears that the POST data sent in the variable content is not received despite it being sent.
UPDATE
When I inspect the JSON sent to my Azure Function in the logger it looks like this.
{"FormName":"UpdateMileage","FormData":[{"Key":"enteredmileage","Value":100},{"Key":"todaysdate","Value":"01/01/2017"}],"Profile":{"EmailAddress":"unittest#mycompany.co.uk","ID":9999999}}
Which doesn't work.
But if I hard code the following JSON from my Azure Function it works correctly (the double quotes are needed to escape the back-slashes).
"\"{\\\"FormName\\\":\\\"UpdateMileage\\\","\\\"FormData\\\":"[{\\\"Key\\\":\\\"enteredmileage\\\",\\\"Value\\\":100},"{\\\"Key\\\":\\\"todaysdate\\\",\\\"Value\\\":\\\"01/01/2017\\\"}],"\\\"Profile\\\":"{\\\"EmailAddress\\\":\\\"unittest#mycompany.co.uk\\\","\\\"ID\\\":9999999}}\""
The problem therefore appears to be the formatting of the JSON that is being sent from my Azure Function, but I don't how I would convert my JSON into this format.
The problem was caused by the fact that I was sending JSON to my ASP.NET Web API service, but sending it as a string type. This is wrong.
The following article explains the correct approach when sending JSON data as a POST request.
I'm having trouble getting my servicestack json client to format a REST Post request.
I'm trying to post to my login service with a raw json body of
{"Uname":"joe", "Password":"test"}
but the post methods is actually mistakenly sending this
{"login":""}
Here's the code I'm using.
JsonServiceClient.HttpWebRequestFilter = filter =>
{
filter.Headers.Add(string.Format("X-API-Key: {0}", "test"));
};
var client = new JsonServiceClient(url);
var url = "/login";
var login = new LoginModel { Uname = uname, Password = pwd };
return client.Post<UserCredentials>(url, login);
How should I structure the parameter object so that it serializes to the correctly to the intended raw value in the post request? Additionally, can I just pass in a dictionary or a more generic object so that I don't have to create a LoginModel class or struct?
It turns out the issue was that I was using public fields instead of public properties in my LoginModel. Changing it to properties fixed it.
I'm trying to consume a web service with the Web API client library. My problem is that the ReadAsAsync doesn't seem to want to fully deserailize the returned object when the submitting function uses a POST method.
If I get the response as a string and manually deserailize it works. (I get a apmsgMessage with all the fields populated)
HttpClient client = GetClient();
var response = client.PostAsJsonAsync("api/robot/Preview", ad).Result;
var msg = response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<apmsgMessage>(msg.Result);
I originally tried the code below which returns an apmsgMessage Object, but all the fields are null.
HttpClient client = GetClient();
var response = client.PostAsJsonAsync("api/robot/Preview", ad).Result;
var msg = response.Content.ReadAsAsync<apmsgMessage>().Result;
return msg;
My question is why dosn't my orginal (the PostAsJsonAsync) return a apmsgMessage fully populated. Am I doing somethign wrong with the ReadAsAsync?
I just had the same issue, and in my case I solved it by removing the [Serializable] attribute from the class.
I don't know why this attribute conflicts with the deserialization process, but as soon as I took that out, the ReadAsAsync method worked as expected.
ServiceStack services are great for responding with the content type that's requested in the Accept header. But if I need to close/end the response early from within a request filter, is there a way to respond with the proper content type? All I have access to in a request filter is the raw IHttpResponse so it seems to me that the only option is to tediously, manually check the Accept header and do a bunch of switch/case statements to figure out which serializer to use and then write directly to the response.OutputStream.
To further illustrate the question, in a normal service method you can do something like this:
public object Get(FooRequest request)
{
return new FooResponseObject()
{
Prop1 = "oh hai!"
}
}
And ServiceStack will figure out what content type to use and which serializer to use. Is there anything similar to this that I can do within a request filter?
ServiceStack pre-calculates the Requested Content-Type on a number of factors (e.g. Accept: header, QueryString, etc) it stores this info in the httpReq.ResponseContentType property.
You can use this along with the IAppHost.ContentTypeFilters registry which stores a collection of all Registered Content-Type serializers in ServiceStack (i.e. built-in + Custom) and do something like:
var dto = ...;
var contentType = httpReq.ResponseContentType;
var serializer = EndpointHost.AppHost
.ContentTypeFilters.GetResponseSerializer(contentType);
if (serializer == null)
throw new Exception("Content-Type {0} does not exist".Fmt(contentType));
var serializationContext = new HttpRequestContext(httpReq, httpRes, dto);
serializer(serializationContext, dto, httpRes);
httpRes.EndServiceStackRequest(); //stops further execution of this request
Note: this just serializes the Response to the Output stream, it does not execute any other Request or Response filters or other user-defined hooks as per a normal ServiceStack request.