I am quite new to RestKit. I know that the Object Mapping of Restkit is very powerful. However, in some case, I just want to map to a simple variable. For example, take a look at the following response:
{
"response": 400,
"result": {
"error_message": "Invalid session token"
}
}
I just want to know the value of "response" or "error_message". It's quite wasteful to create 2 classes "response", and "result", since these classes have only few fields.
Any recommendation is welcome.
You can create a single class with response and message properties, then use mappings:
#"response" : #"response",
#"result.error_message" : #"message"
Or you can just map into a dictionary for error responses and then use the keypath to access the message.
Related
I use model validation in Asp.Net Core and it returns 400 errors like that:
{
"errors": {
"MyProperty": [
"Error 1",
"Error 2"
]
},
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "0HLRTF1TPCO60:00000002"
}
I do have my custom validation that does not use Asp.Net core built-in mechanisms, but I'd like to generate the error in exact same format so that it would be easier for users to consume. I can of course just generate JSON myself, but I think there is some built-in API to generate such an error from model, though I cannot manage to find what should I call.
P.S. I want to do this in middleware
I have figured out myself how this can be achieved:
var modelState = new ModelStateDictionary();
modelState.AddModelError("FieldName", "ErrorMessage");
var details = new ValidationProblemDetails(modelState);
details.Status = (int?) HttpStatusCode.BadRequest;
details.Extensions["traceId"] = context.TraceIdentifier;
The details can later be serialized to JSON.
I'm trying to update the fields associated with a list item via Graph Explorer, https://developer.microsoft.com/en-us/graph/graph-explorer (or a REST API call). For one of the fields, its value can be one item from a term set (managed meta data). I can see each of the elements in the term set and get each termguid when I visit https://XXX.sharepoint.com/Lists/TaxonomyHiddenList/AllItems.aspx.
I'm trying to do a PATCH request with a URL of something like https://graph.microsoft.com/beta/sites/XXX.sharepoint.com,FOO,BAR/drive/root/children/Test%20Document.txt/listItem/fields (or https://graph.microsoft.com/v1.0/sites/XXX.sharepoint.com,FOO,BAR/drive/list/items/1/fields) to identify the fields associated with a specific item
To update the CakeType field, I've set the request body to the following:
{
"CakeType": {
"Label": "Apple",
"TermGuid": "3a3ad73f-94ca-4d1e-a25c-XXXX",
"WssId": -1
}
}
When I then press the Run Query button, I get an InvalidClientQueryException with a message of "A value without a type name was found and no expected type is available. When the model is specified, each value in the payload must have a type which can be either specified in the payload, explicitly by the caller or implicitly inferred from the parent value."
So, I've been trying to figure out what datatype to specify and how to... In various examples online, I've seen adding a field named __metadata and others adding #odata.type, like CakeType#odata.type for the case here. I've tried adding these lines within the CakeType JSON and outside it, for the whole structure. Neither worked...
{
"CakeType": {
"__metadata" : {"type" : "SP.Taxonomy.TaxonomyFieldValue" },
"Label": "Apple",
"TermGuid": "3a3ad73f-94ca-4d1e-a25c-XXXX",
"WssId": -1
}
}
or
{
"__metadata" : {"type" : "SP.Taxonomy.TaxonomyFieldValue" },
"CakeType": {
"Label": "Apple",
"TermGuid": "3a3ad73f-94ca-4d1e-a25c-XXXX",
"WssId": -1
}
}
I've also tried using the field name in the type which I thought I saw somewhere...
"__metadata" : {"type" : "SP.Data.CakeType" },
and tried
"CakeType#odata.type" : "SP.Taxonomy.TaxonomyFieldValue" ,
"CakeType#odata.type" : "SP.Data.CakeType",
"#odata.type" : "SP.Taxonomy.TaxonomyFieldValue" ,
The only things that gave a different error message was when I put "CakeType#odata.type" : "SP.Taxonomy.TaxonomyFieldValue" , immediately after the opening { or without the CakeType part within the CakeType...
{
"CakeType#odata.type" : "SP.Taxonomy.TaxonomyFieldValue" ,
"CakeType": {
"Label": "Apple",
"TermGuid": "3a3ad73f-94ca-4d1e-a25c-XXXX",
"WssId": -1
}
}
and
{
"CakeType": {
"#odata.type" : "SP.Taxonomy.TaxonomyFieldValue" ,
"Label": "Apple",
"TermGuid": "3a3ad73f-94ca-4d1e-a25c-XXXXX",
"WssId": -1
}
}
Each gave an error of "A type named 'SP.Taxonomy.TaxonomyFieldValue' could not be resolved by the model. When a model is available, each type name must resolve to a valid type."
This makes me think that I have the right field name but the wrong type...
So... what should I be naming the type so I can update the managed meta data field? or... what must the JSON be if the above structure is so far off... or how can I update the field strictly using the Graph API.
Thanks.
I thought looking at schema extensions might help (GET https://graph.microsoft.com/v1.0/schemaExtensions) but it didn't...
Ultimately, I'm trying to update the managed meta data field from Java with the classes in com.microsoft.graph.... so if I can figure out the right stuff with Graph Explorer, I can then move over to Java. I've seen some examples of such in other languages but can't figure out the right way to do same in Java.
Here is how I was finally able to do this.
First you need the id of the hidden field which is the displayName corresponding to your field CakeType which should be CakeType_0.
I used this REST call to get find the id:
https://graph.microsoft.com/v1.0/sites/{sitid}/lists/{listid}/items?expand=hidden
This will return all your fields and you want the one with the _0 suffix:
..."displayName": "Cake_0",...
"name": "d39a5181f12f41a483acb1a4e47477b1"...
It is this name id you need to use to update the field.
So then the PATCH call on your item is like this:
https://graph.microsoft.com/v1.0/sites/{sitid}/lists/{listid}/items/{itemid}
Then the payload syntax is like this:
{"{FieldID}":"{TermNumber};#{Term}|{TermGuid}"}
So it would look like this (assuming Apple is the 4th tag although I think -1 might work there too):
{"d39a5181f12f41a483acb1a4e47477b1":"4;#Apple|3a3ad73f-94ca-4d1e-a25c-XXXX"}
For more than one tag separate them with ;# all within the same quoted string
I was having the same issue, and found this: https://microsoftgraph.uservoice.com/forums/920506-microsoft-graph-feature-requests/suggestions/33421180-support-for-setting-sharepoint-managed-metadata-t
The feature request:
Support for setting SharePoint Managed Metadata (taxonomy) column values and other complex column types on items via the Graph API
The response:
Thank you for your feedback! This work is on the backlog and currently isn’t scheduled. The feature will be updated here once dev work has started. -EY
I was wondering what the easiest way would be to return clean json from the result of a discriminated union in WebApi? This use case is for business logic only and not used for http errors, etc - those get handled in the pipeline and get returned to user as usual (404, 500, etc)
For example:
type ServiceResult<'a> = { Message:string; Payload:'a }
type ServiceResponse<'a> =
| Success of ServiceResult<'a>
| Fail of ServiceResult<string>
Returns Either:
{
"Case": "Fail",
"Fields": [
{
"Message": "Error performing business logic, your x is not in the y.",
"Payload": "I just couldnt do it"
}
]
}
...or...
{
"Case": "Success",
"Fields": [
{
"Message": "",
"Payload": { "FirstName": "Johnny", "LastName":"Smith" }
}
]
}
Where I would like to have only the service result returned like:
{
"Message": "",
"Payload": { "FirstName": "Johnny", "LastName":"Smith" }
}
... or ...
{
"Message": "Error during operation due to spite.",
"Payload": "I just couldnt do it"
}
I have tried IdiomaticDuConverter:
https://gist.github.com/isaacabraham/ba679f285bfd15d2f53e
but it didnt work. The closest i have seen is Microsoft.FSharpLu.Json but it doesnt have a MediaTypeFormatter to plug into the pipeline.
I know i can use Lu and create my own MediaTypeFormatter but I feel like there has to be an easier way (like some Json.Net option I am missing).
Can you point me in the right direction?
thanks :-)
While there may be corner cases where the return representation you're asking about is the correct design, in general this isn't good HTTP API design. ASP.NET Web API returns HTTP responses, so the implication of returning
{
"Success": false,
"Message": "Error during operation due to spite.",
"Payload": "I just couldnt do it"
}
is that this value is being returned as part of a 200 OK response. This puts an extra burden on clients, because they now have to handle not only HTTP errors (which can still happen), but also can't trust that 200 OK actually meant success.
Instead, if there's an error, return the appropriate HTTP status code.
This also solves the problem, and makes your F# code easy to write. In a Controller, you'd basically do something like this:
member this.Get() =
let result = // produce the result somehow...
match result with
| Success x -> this.Ok x :> IHttpActionResult
| Fail msg -> this.BadRequest msg :> IHttpActionResult
For simplicity's sake, this example returns 400 Bad Request on a Fail case, but if this case represents an internal error, perhaps 500 Internal Server Error would be more appropriate.
You can write a custom JSON.NET serializer for your ServiceResponse type that would simply skip the case label and delegate serialization to the nested ServiceResult.
The real question here is why do you even have this problem? You already carry the success/failure status in the record, the DU doesn't offer any additional information. What's more, with the setup you have, you can easily represent seemingly undesirable states like this:
Success <| { Success = false; Message = "necktie"; Payload = "bacon" }
Why not just drop it and pass around the record only, avoiding the serialization problem altogether?
I get an error when I call Put to my server using WebApi Odata v4.
{
"error": {
"code": "",
"message": "The request is invalid.",
"innererror": {
"message": "job : The property 'test' does not exist on type 'Model.Temp'. Make sure to only use property names that are defined by the type.\r\n",
"type": "",
"stacktrace": ""
}
}
}
this error happens because the property "test" is not set in the Model "Temp". it is actually added by javascript, and only used in client-side
How do I make so that OData will just ignore properties that are not available in the Model ?
There is a way to deal with your scenario. It is not to ignore the properties, but to accept them by defining the entity type as an open type so that it can accept dynamic properties which are not defined in the model from the client and store them for future queries if necessary.
You can find the following tutorial for implementing an open type support: http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/use-open-types-in-odata-v4
I'm trying to use the create_flow endpoint to the Survey Monkey API. It is sending back a status 3 message with the following error:
additional properties not defined by 'properties' are not allowed in field '_data'
I'm able to do successfully use all other API endpoints and have a valid API key and durable OAuth token.
Here's an example JSON body that I'm sending to: https://api.surveymonkey.net/v2/batch/create_flow?api_key=apikeyhere
{
"survey": {
"template_id": "566",
"survey_title": "test1",
"collector": {
"type": "email",
"name": "collector1",
"recipients": [
{
"email": "email#example.com"
}
]
},
"email_message": {
"reply_email": "myemail#example.com",
"subject": "this is a test"
}
}
Note: JSON formatting here is being generated automatically using RJSONIO
Any ideas what might be causing the error? It seems like all fields are correctly named and where they're supposed to be, so I'm not sure what the problem is.
It's a bad error message unfortunately - it's a known issue. It means you are providing extra keys that are not part of the create_flow schema.
The issue here is that the "email_message" and "collector" keys have been nested inside of "survey", instead of being in the main JSON body like the "survey" key. Move them out a level and it should work.