How to add Error Code to validation attributes in MVC? - asp.net-mvc

I'd like to be able to specify an error code to be returned from my API along with the error message in the event that validation fails. The aim is to specify a validation attribute on a property such as:
[Range(1, int.MaxValue, ErrorMessage = "Page must be 1 or greater", ErrorCode = 1234)]
And, in the event that someone requests page 0, return a 400 Bad Request with a JSON error object in the body like this:
{
"errorCode": 1234,
"errorMessage": "Page : Page must be 1 or greater"
}
I already have a custom ModelValidationFilter which returns an array of error messages from the ModelStateDictionary, so that's all working, but I can't see a straightforward way of getting the error code included in there too without overriding all of the MVC model validation classes.
This seems like a problem which should already have been solved by someone at some point, but I can't find anything to support that theory.

Related

Serverless - Change the content before deploy

I'm using Serverless for working with our aws lambda / appsync.
For Error Handling, we are keep erro code with message in a json file. The Codes will be unique. Something like this:
//error-code.json
{
"1"": { code: 1, message: "Invalid User Input"},
"2"": { code: 2, message: "Invalid Input"},
//... so on
}
This wil lbe deploy as layer and all the lambda will use it. Issue is we cannot use it in the resolve template. There are some of the resolver will be only template file. These template files cannot access the json file nor can access the layer. How can I use the error-code.json here?
Solution 1:
Manually write the error code in templates and make sure there are alway unique. Something like this:
#set(#errorInfo = {
"erroCode": "1",
"errorMessage": "Invalid Input"
})
$util.error("Invalid Input", "errorType", $ctx.arguments,#errorInfo)
Rejected: Becasue we have to manually check everytime for the unique of error code. In case of lot of template file, we cannot rely on it.
Solution 2:
Create a table with error code (unique) and error message. Use this table to send error from template.
Rejected: Because we use multiple app sync instance and they all connect to dirferent database. So we have to make this table in all database, and thus unique across the app-sync is not maintained.
Solution 3:
Write the placeholder in vtl where we want to send the error. Before Deploy, replace the placeholder with the actual code using pre-hook script, but not in the actual vtl file but in the generated package that serverless deploy. Does Serverless even such thing?
if your errors are all static, there is one more option for consideration.
You create one more file that holds all errors defined in Velocity.
$util.qr( $ctx.stash.put("errors", {}) ) $util.qr(
$util.qr( $ctx.stash.errors.put("ONE", { "code": 1, "message": "Invalid User
Input"} )
...
$util.qr( $ctx.stash.errors.put("TWENTY", { "code": 20, "message": "20th error description"} )
For every velocity resolver that throws errors, you inject pre-defined errors at the beginning of its request mapping's file. Whenever you want to throw an error, it's done by retrieving a pre-defined error from $ctx.stash
$util.error ( $ctx.stash.errors.ONE.message, $ctx.stash.errors.ONE.code )
The error file is generated from error-code.json, or manually typed again for simplicity. $ctx.stash is used because stash is accessible from everywhere in a resolver, including pipeline ones.

Google reCAPTCHA Enterprise Unknown field error when Create Assessment

I did follow their documentation on https://googleapis.dev/ruby/google-cloud-recaptcha_enterprise-v1/latest/index.html
I first added the env variable RECAPTCHA_ENTERPRISE_CREDENTIALS then run the
client = ::Google::Cloud::RecaptchaEnterprise::V1::RecaptchaEnterpriseService::Client.new
documentation says response = client.create_assessment request but documentation didn't add sample request so I did assume that it will look like in this documentation https://cloud.google.com/recaptcha-enterprise/docs/create-assessment
{
"event": {
"token": "token",
"siteKey": "key"
}
}
But when I execute the client.create_assessment it is giving me error ArgumentError: Unknown field name 'event' in initialization map entry.
I also tried to follow this https://googleapis.dev/ruby/google-cloud-recaptcha_enterprise-v1/latest/Google/Cloud/RecaptchaEnterprise/V1/RecaptchaEnterpriseService/Client.html#create_assessment-instance_method
where the parameters is request and also gives me error ArgumentError: Unknown field name 'request' in initialization map entry.
What could be the correct parameter/request for creating assessment?
Gem I used is google-cloud-recaptcha_enterprise-v1 and google-cloud-recaptcha_enterprise
So I solve this issue by using client.create_assessment(parent: "projects/{your project-id}", assessment: event) my event value was event = Google::Cloud::RecaptchaEnterprise::V1::Event.new(token: "token from execute", site_key: "your site key")
It solves the error and answers the question (but another error after this one occurred about permission denied). I Will update once resolved.

"Exception Occurred" with addSiteAccount1

After having gotten a site's login form from getSiteLoginForm, I'm attempting to add a site, but I'm receiving
{ :errorOccurred=>"true", :exceptionType=>"Exception Occurred", :referenceCode=>"_fa9ede97-1792-45ca-b147-005ec4002d33" }
The URL I'm POSTing to (in Rails) is:
https://consolidatedsdk.yodlee.com/yodsoap/srest/private-fairshare/v1.0/jsonsdk/SiteAccountManagement/addSiteAccount1
and this is the POST data:
cobSessionToken=REDACTED
userSessionToken=REDACTED
siteId=11671
credentialFields.enclosedType=com.yodlee.common.FieldInfoSingle
credentialFields[0][displayName]=User Name
credentialFields[0][fieldType.typeName]=TEXT
credentialFields[0][isEditable]=true
credentialFields[0][name]=LOGIN
credentialFields[0][value]=testuser
credentialFields[0][valueIdentifier]=LOGIN
credentialFields[0][valueMask]=LOGIN_FIELD
credentialFields[1][displayName]=Password
credentialFields[1][fieldType.typeName]=IF_PASSWORD
credentialFields[1][isEditable]=true
credentialFields[1][name]=PASSWORD
credentialFields[1][value]=testpass
credentialFields[1][valueIdentifier]=PASSWORD
credentialFields[1][valueMask]=LOGIN_FIELD
I've triple checked the parameters, and they seem to match up with the documentation.
Is there something I'm missing?
Looking at the documentation it looks like there's a mismatch in the format of your parameters.
For example, you have the field credentialFields[0][displayName], but in the documentation it's referred to as credentialFields[0].displayName. Is is possible that the API expects fields in this format?
If the API does expect fields in the credentialFields[0][displayName] then it would make sense for the credentialFields.enclosedType field to follow the same format. In that case it should be credentialFields[enclosedType].

404 response when creating a course with the API

I am attempting to create a course with the API, and no matter how I tweak what I am sending I keep getting back the same 404 error. I am posting the following to /d2l/api/lp/1.4/courses/ in our test instance.
{
"Name":"STLR Course-112",
"Code":"STLR.112.201420",
"Path":"",
"CourseTemplateId":22462,
"SemesterId":22460,
"StartDate":"2014-05-07T12:00:00.000Z",
"EndDate":"2014-05-07T13:00:00.000Z",
"LocaleId":null,
"ForceLocale":false,
"ShowAddressBook":false
}
I can confirm with a test instance here that this API works with data almost identical to the block you provide here. POSTing a body like this (white space added for clarity):
{"CourseTemplateId": 8082,
"LocaleId": null,
"Code": "STLR.112.201420",
"Name": "STLR Course-112",
"Path": "",
"ShowAddressBook": false,
"EndDate": "2014-05-07T13:00:00.000Z",
"StartDate": "2014-05-07T12:00:00.000Z",
"ForceLocale": false,
"SemesterId": 6984}
Gets me a 200 with a response like this (white space added for clarity):
{"Identifier":"114119",
"Name":"STLR Course-112",
"Code":"STLR.112.201420",
"IsActive":true,
"Path":"/content/enforced/114119-STLR.112.201420/",
"StartDate":"2014-05-07T12:00:00.000Z",
"EndDate":"2014-05-07T13:00:00.000Z",
"CourseTemplate":{"Identifier":"8082",
"Name":"ExtensibilityTemplate",
"Code":"EXT-TMPL"},
"Semester":{"Identifier":"6984",
"Name":"Fall 2011",
"Code":"FA2011"},
"Department":{"Identifier":"8081",
"Name":"Extensibility",
"Code":"EXT"}
}
It appears to me that the only differences between my input block and yours are the IDs provided for course template and semester, so that I could hook the new course into my local test instance instead of the IDs for those orgunits in yours. Otherwise, it appears the input properties are identical.
Some things you could look at:
Ensure you're using the right Org Unit Id values for your course template and your semester
Ensure that your LMS is configured to enforce content paths for new org units: this should then provoke the LMS to auto-create the path for you when you create a course offering; if you don't have content path enforcement on, then you might have to instead specify a valid content path for your course offering on create, and passing in an empty string probably won't be a valid path, and thus you might get a 404 back because the API service handler "can't find the content path" you've specified.
Is there a particular message that comes back with the 404?

Best way to handle errors in Grails domain class validation

We have an API command like "student/create" to create a new student object. The code looks like this:
def student = new Student(firstName: firstName, lastName: lastName, email: email)
if (! student.validate()) {
response.error = "UNKNOWN_ERROR" // in case we can't find anything better
student.errors.allErrors.each { error ->
// set response.error to an appropriate value
println error
}
} else {
student.save()
}
Our goal is to give a reasonable error message like "EMAIL_DUPLICATE" or "FIRSTNAME_LENGTH" on a validation fail, so we want to test the errors we get against a set of expected errors so we can respond like that.
Here's what we get from that println:
Field error in object 'com.example.Student' on field 'email': rejected value [student#example.com]; codes [com.example.Student.email.unique.error.com.example.Student.email,com.example.Student.email.unique.error.email,com.example.Student.email.unique.error.java.lang.String,com.example.Student.email.unique.error,student.email.unique.error.com.example.Student.email,student.email.unique.error.email,student.email.unique.error.java.lang.String,student.email.unique.error,com.example.Student.email.unique.com.example.Student.email,com.example.Student.email.unique.email,com.example.Student.email.unique.java.lang.String,com.example.Student.email.unique,student.email.unique.com.example.Student.email,student.email.unique.email,student.email.unique.java.lang.String,student.email.unique,unique.com.example.Student.email,unique.email,unique.java.lang.String,unique]; arguments [email,class com.example.Student,student#example.com.org]; default message [Property [{0}] of class [{1}] with value [{2}] must be unique]
How can I figure out that this means the email is already used in the database so that I can tell the API user that?
(to be clear, I want to give a computer-readable message like "EMAIL_DUPLICATE" instead of something like "Property email of class Student with value student#example.com must be unique")
Not sure it would work in more situations than just this one, but does:
println "${error.objectName}_${error.codes[-1]}".toUpperCase()
Get you anywhere near?

Resources