[HttpPost]
[Authorize("PublicCreateOrder")]
public async Task<ActionResult> CreateOrder(CancellationToken cancellationToken)
{
var watch = System.Diagnostics.Stopwatch.StartNew();
//--------------> Performance measure Start <------------ FROM THIS POINT
StreamReader requestReader = new StreamReader(Request.Body);
JObject jsonRequest;
try
{
jsonRequest = JObject.Parse(await requestReader.ReadToEndAsync());
}
catch (Exception ex)
{
return BadRequest("Please send a metadata has the type of JSON.");
}
var filePath = System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + "\\OrderSchema.json";
using (StreamReader fileReader = new StreamReader(filePath))
{
JSchema jsonSchema = JSchema.Parse(await fileReader.ReadToEndAsync());
IList<ValidationError> errors;
if (!jsonRequest.IsValid(jsonSchema, out errors))
{
List<ValidationError> newErrors = new List<ValidationError>();
new List<ValidationError>(errors).ForEach(error =>
{
if (error.ChildErrors.Count > 0)
newErrors.AddRange(error.ChildErrors);
else
newErrors.Add(error);
});
var errorsItems = errors.Select(error => new GetSchemaValidationResponse
{
Message = error.Message,
ErrorType = error.ErrorType.ToString(),
LineNumber = error.LineNumber,
LinePosition = error.LinePosition,
Path = error.Path
}).ToList();
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
//--------------> Performance measure Finish<------------ TO THIS POINT
return BadRequest(errorsItems);
}
}
CreateOrderRequest request = JsonConvert.DeserializeObject<CreateOrderRequest>(jsonRequest.ToString());
In this code block i apply a json schema validation against an http request with json body. But because of this validation will perform against every request maybe it will cause a performance issues. For now, this code block took under 2ms but i want to improve the performance. Do you have any idea?
And also if you have an advice about code quality, i would be glad to know it.
-
\$\begingroup\$ Trying to understand the code. Why not use standard model binding for the CreateOrderRequest since you deserialize to it? Is the validation dynamic where you can't have it in the standard IValidatableObject Interface? \$\endgroup\$CharlesNRice– CharlesNRice2022年09月29日 19:33:34 +00:00Commented Sep 29, 2022 at 19:33
-
\$\begingroup\$ It is because of i must apply json validation against stream object. If i make a model binding, CreateOrderRequest object will add all properties to json request. For example i don't wanna send a value with a specific key in json request and after that model binding see it ass null(or 0 for int etc.) with key. But i dont wanna see this key because i didn't send it. \$\endgroup\$Cengiz Ergün– Cengiz Ergün2022年09月29日 20:21:16 +00:00Commented Sep 29, 2022 at 20:21
2 Answers 2
Useless Copying
You're creating a lot of lists for no reasons. No need to copy one list to another just to iterate over it.
Separation of Concerns
The schema validation code pollutes the controller method. It's much better placed in a custom model binder or Filter
It is not a full review, just a quick observation: Rather than loading and parsing the schema each and every time when this method is being called you should do it only once, if the schema is not changing while the application is running.
You can do it eagerly inside the static constructor for example or lazily via the Lazy<T>
type.
-
1\$\begingroup\$ Schema is not changing while the application is running. Thank you so much. I will apply your advice. \$\endgroup\$Cengiz Ergün– Cengiz Ergün2022年09月29日 14:58:02 +00:00Commented Sep 29, 2022 at 14:58