I am testing the api created using ServiceStack using SoapUI and when I try to send the required DataMember thru headers, the api returns the correct values. When I try to send the required DataMember thru Body, I am getting the below error... Please help
Request sent through the body
<GetProductDetailsReq>
<AToken>ck0b0YYBPkrnVF/j6e16DUPzxLX2SMCXewoR4T</AToken>
</GetProductDetailsReq>
POST http://localhost/ServiceStackAPI/GetProductDetails HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: application/xml
Accept: application/xml
Content-Length: 777
Host: localhost
Proxy-Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
Response Status
Error Code
SerializationException Message
Could not deserialize 'application/xml' request using ServiceModel.DTO.GetProductDetailsReq' Error:
System.Runtime.Serialization.SerializationException: Error in line 1
position 66. Expecting element 'GetProductDetailsReq' from namespace
''.. Encountered 'Element' with name 'GetProductDetailsReq', namespace
'http://schemas.servicestack.net/types'. at
System.Runtime.Serialization.DataContractSerializer.InternalReadObject(XmlReaderDelegator
xmlReader, Boolean verifyObjectName, DataContractResolver
dataContractResolver) at
System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator
reader, Boolean verifyObjectName, DataContractResolver
dataContractResolver) at
System.Runtime.Serialization.XmlObjectSerializer.ReadObject(XmlDictionaryReader
reader) at
System.Runtime.Serialization.XmlObjectSerializer.ReadObject(Stream
stream) at ServiceStack.Text.XmlSerializer.DeserializeFromStream(Type
type, Stream stream) at
ServiceStack.WebHost.Endpoints.Support.EndpointHandlerBase.CreateContentTypeRequest(IHttpRequest
httpReq, Type requestType, String contentType) Stack Trace
at ServiceStack.WebHost.Endpoints.Support.EndpointHandlerBase.CreateContentTypeRequest(IHttpRequest
httpReq, Type requestType, String contentType) at
ServiceStack.WebHost.Endpoints.RestHandler.GetRequest(IHttpRequest
httpReq, IRestPath restPath) at
ServiceStack.WebHost.Endpoints.RestHandler.ProcessRequest(IHttpRequest
httpReq, IHttpResponse httpRes, String operationName)
Check the SOAP Limitations to ensure you're creating Services that can be sent in SOAP, i.e. If the Request DTO is called GetProductDetails then it must return a Response DTO called GetProductDetailsResponse. Also you need to ensure your DTO's have [DataContract] on all types and [DataMember] on all public properties and that your DTO's are in a single namespace.
The other issue with this request is that you're using the SOAP requests to wrong endpoint address. i.e. The SOAP endpoint is either /soap11 or /soap12. In the above example it's attempting to send it to the /GetProductDetails custom HTTP route, when for SOAP it needs to be either /soap11 or soap12.
If you did just want to just send XML over HTTP then you should just send the raw XML payload which you can find out what it looks like by serializing the Request DTO, e.g:
string requestXml = new GetProductDetails { ... }.ToXml();
Which you can easily send with HTTP Utils:
var responseXml = "http://localhost/ServiceStackAPI/GetProductDetails"
.PostXmlToUrl(xmlRequest);
var responseDto = responseXml.FromXml<GetProductDetailsResponse>();
Assuming you have a [Route("/GetProductDetails")] defined on the GetProductDetails Request DTO.
Related
We have a basic servicestack frontend that sends using the jsonclient to backend services and works for the past few years.
I am trying to investigate why we are receiving the below exception on any frontend JSON Client.get requests,
System.NullReferenceException
Object reference not set to an instance of an object.
System.NullReferenceException: Object reference not set to an instance of an object.
at System.Collections.Specialized.NameObjectCollectionBase.BaseGetAllKeys()
at System.Collections.Specialized.NameValueCollection.get_AllKeys()
at ServiceStack.PclExportClient.AddHeader(WebRequest webReq, NameValueCollection headers)
at ServiceStack.ServiceClientBase.PrepareWebRequest(String httpMethod, String requestUri, Object request, Action`1 sendRequestAction)
at ServiceStack.ServiceClientBase.SendRequest(String httpMethod, String requestUri, Object request)
at ServiceStack.ServiceClientBase.Send[TResponse](String httpMethod, String relativeOrAbsoluteUrl, Object request)
at ABC.api.InitializationService.Any(InitializationRequest request) in C:\.....\api\InitializationService.cs:line 27
It's strange, and i'm trying to reproduce this issue by hitting the breakpoint, and nulling / modifying the headers, but can't reproduce or figure out what this issue is.
To me, doesn't the exception imply the header base keys are null, and it can't be retrieved - but how does that occur ?
Using ServiceStack 5.80
ASP.NET MVC
.Net Framework 4.6.1
EDIT:
Calling line of code that produces this issue is
var deviceResult = client.Get(new DRequest{ U = r.D });
To register a webhook on Dynamics 365 there is a tool called Plug-in Registration (https://learn.microsoft.com/en-us/powerapps/developer/data-platform/register-web-hook).
However, I would like to automate the webhook registration process and thus would like to use the Web API endpoint for webhook registration:
/api/data/v9.2/serviceendpoints
The problem I have is the setting of the value for the parameter authvalue in the JSON request body, because I want to use Http Header authtype:
{
"name": "Test Webhook",
"url": "https://myendpoint",
"contract": 8,
"authtype": 5,
"authvalue": "<========= ??? what comes here ???"
}
Assuming I want to have this header be sent to my webhook endpoint:
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
What would be the value of authvalue in the JSON above ?
The value should be a string according to the data type of authvalue, but how that should be formatted?
If I use the value Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ= as is for authvalue,
when the webhook is fired, I got the following error in System Job:
Plugin Trace:
[Microsoft.Crm.ServiceBus: Microsoft.Crm.ServiceBus.WebhookPlugin]
[ad9a4124-ab57-ec11-8f8f-6045bd8aed3b: Test for Step Creation]
Error Message:
System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]:
The webhook call failed because of invalid http headers in authValue.
Check if the authValue format, header names and values are valid for
your Service Endpoint entity. (Fault Detail is equal to Exception
details: ErrorCode: 0x80050203 Message: The webhook call failed
because of invalid http headers in authValue. Check if the authValue
format, header names and values are valid for your Service Endpoint
entity. TimeStamp: 2021-12-08T10:15:26.8637496Z
-- Exception details: ErrorCode: 0x80040216 Message: Received exception when adding custom http headers: for
OrgId:xxxxxx-925f-4958-9aee-xxxxxxxxxxxx, serviceEndpointId:
c099d16c-a057-ec11-8f8f-6045bd8aed3b, name: Test Webhook,
exception:System.Xml.XmlException: Data at the root level is invalid.
Line 1, position 1. at System.Xml.XmlTextReaderImpl.Throw(Exception
e) at System.Xml.XmlTextReaderImpl.ParseRootLevelWhitespace() at
System.Xml.XmlTextReaderImpl.ParseDocumentContent() at
System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean
preserveWhitespace) at System.Xml.XmlDocument.Load(XmlReader
reader) at System.Xml.XmlDocument.LoadXml(String xml) at
Microsoft.Crm.ServiceBus.WebhookClient.ExtractKe...).
For HtppHeader authentication type the key value pair for AuthValue must be set in the following xml format:
<settings><setting name="Authorization" value="Basic dXNlcm5hbWU6cGFzc3dvcmQ=" /></settings>
I have a .NET Core Web API that is returning a 415 Unsupported Media Error when I try to post some data to it that includes some json. Here's part of what is returned in the Chrome Debugger:
Request URL:http://localhost:51608/api/trackAllInOne/set
Request Method:POST
Status Code:415 Unsupported Media Type
Accept:text/javascript, text/html, application/xml, text/xml, */*
Content-Type:application/x-www-form-urlencoded
action:finish
currentSco:CSharp-SSLA:__How_It_Works_SCO
data:{"status":"incomplete","score":""}
activityId:13
studentId:1
timestamp:1519864867900
I think this has to do with my controller not accepting application/x-www-form-urlencoded data - but I'm not sure. I've tried decorating my controler with Consumes but that does not seem to work.
[HttpPost]
[Route("api/trackAllInOne/set")]
[Consumes("application/x-www-form-urlencoded")]
public IActionResult Post([FromBody] PlayerPackage playerPackage)
{ etc..}
Any help greatly appreciated.
The following code worked fine in .NET 4.6.1 and I am able to capture and process the posts shown above.
[ResponseType(typeof(PlayerPackage))]
public async Task<IHttpActionResult> PostLearningRecord(PlayerPackage playerPackage)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var id = Convert.ToInt32(playerPackage.ActivityId);
var learningRecord = await _context.LearningRecords.FindAsync(id);
if (learningRecord == null)
return NotFound();
etc...
Try using [FromForm] instead of [FromBody].
public IActionResult Post([FromForm] PlayerPackage playerPackage)
FromBody > Bind from JSON
FromForm > Bind from Form parameters
You can also remove [FromBody] altogether and trial it then. Because you are expecting form-urlencoded should tell it to bind to object.
For PlayerPackage, the request should send a PlayerPackage Json Object, based on your description, you could not control the request which is posted from other place.
For the request, its type is application/x-www-form-urlencoded, it will send data with {"status":"incomplete","score":""} in string Format instead of Json object. If you want to accept {"status":"incomplete","score":""}, I suggest you change the method like below, and then convert the string to Object by Newtonsoft.Json
[HttpPost]
[Route("~/api/trackAllInOne/set")]
[Consumes("application/x-www-form-urlencoded")]
public IActionResult Post([FromForm] string data)
{
PlayerPackage playerPackage = JsonConvert.DeserializeObject<PlayerPackage>(data);
return Json(data);
}
This did the trick for me:
[HttpPost]
[Consumes("application/x-www-form-urlencoded")]
public IActionResult Post([FromForm]IFormCollection value)
I had the same problem. FormDataCollection has no default constructors which is required by Formatters. Use IFormCollection instead.
Can make setting like as
[HttpPost()]/[HttpGet()]
[Consumes("application/x-www-form-urlencoded")]
public async Task<IActionResult> MethodName([FromForm] IFormCollection value)
don't forget to add [FromForm]
Hi Iam new to Azure functions i am using VS 2017 15.4 and running helloworld function app on local. i was able to do get request on this function but when i perform post on same uri it gives.
mscorlib: Exception while executing function: HelloWorld. System.Net.Http.Formatting: No MediaTypeFormatter is available to read an object of type 'Object' from content with media type 'application/octet-stream'.
can you tell me what i forgot bold line is giving problem in post request, i tried with contentType and without ContentType; with body and without body.
How can i parse Json object in request body in azure function. one way i could was to parse it in string then deserialized using jsonconvert. is their any better way of doing it like valueproviders modelbinders etc.
[FunctionName("HelloWorld")]
public static async Task Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
// parse query parameter
string name = req.GetQueryNameValuePairs()
.FirstOrDefault(q => string.Compare(q.Key, "name", true) == 0)
.Value;
// Get request body
*dynamic data = await req.Content.ReadAsAsync<object>();*
// Set name to query string or body data
name = name ?? data?.name;
return name == null
? req.CreateResponse(HttpStatusCode.BadRequest, "Please pass a name on the query string or in the request body")
: req.CreateResponse(HttpStatusCode.OK, "Hello " + name);
}.
This should work assuming the Content-Type header on your HTTP request is set to application/json.
Note that if the header's value is multipart/form-data, then this is a known bug documented here.
As Connor said as long as the Content-Type header is set to application/json in your request this code will work fine. An issue I have run into though is that the add header functionality when testing azure functions in azure portal doesn't seem to work in this case.
If you can send a request to your function from outside of the test section of azure functions this should work fine.
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.