How to return 400 response using the same format that Asp.Net Core validation uses? - asp.net-mvc

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.

Related

F# WebApi return properly formatted json from a discriminated union

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?

Survey Monkey API Questions

I have a couple questions regarding the survey monkey API. First, I've noticed that the categories that can be assigned to open ended questions don't come through when pulling the details of a response. Is there a way to do this and if not, when will it be added?
Secondly, I've attempting to update the metadata field of a response, yet I'm receiving an invalid schema era.
I'm sending this in the request body:
{
"id": "4472927205",
"metadata": { "category" : "test"
}
}
This is the response I receive:
{
"error": {
"http_status_code": 400,
"message": "Invalid schema in the body provided.",
"id": "1002",
"docs": "https://developer.surveymonkey.com/api/v3/#error-codes",
"name": "Bad Request"
}
}
What is the proper schema for a request?
Categories set in the analyze section are not currently accessible through the API. There is no ETA for that at the moment.
Also the metadata shown in the responses are auto-generated based on other factors (some page logic I believe, contact information - case email collector) and are not updateable at the moment either.
See the docs also you can watch the public docs repo to be notified when the changes you'd like have been released.

Web API OData ignore properties added by client-side

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

RestKit - Map to a simple instance variable

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.

"additional properties" error in Survey Monkey API call

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.

Resources