Is there a native way with Google Cloud Endpoints to mark fields in your model as required, so that during deserialization an error is thrown if a value is not given for that field in the request's JSON body?
For example if you have the following class, you could have some kind of annotation.
public class MyModel {
private String optionalString;
private String requiredString;
public String getOptionalString() {
return optionalString;
}
public String setOptionalString() {
return optionalString;
}
public String getRequiredString() {
return optionalString;
}
#ApiSerializationProperty(required = AnnotationBoolean.TRUE)
public String setRequiredString() {
return optionalString;
}
}
Related
I am using Spring Boot 2. I want to add certain dynamic validations at server side which should be executed in POST REST call. Can these validations be added in form of annotations at parameter level of POST method call?
Below code will help you to achieve server side validation.
Pojo class :
public class Data {
#NotNull
private final String someStringValue;
#Min(1)
private final int someIntValue;
#JsonCreator
public Data(#JsonProperty("someStringValue") String someStringValue, #JsonProperty("someIntValue") int someIntValue) {
this.someStringValue = someStringValue;
this.someIntValue = someIntValue;
}
public String getSomeStringValue() {
return someStringValue;
}
public int getSomeIntValue() {
return someIntValue;
}
For the validation we need a custom class containing the logic:
#Component
public class StringValueValidator {
public void validate(String language, Data data, Errors errors) {
if (!"de-DE".equals(language)) {
if (data.getSomeStringValue().length() > 140) {
errors.reject("someStringValue");
}
}
}
}
controller method :
#RequestMapping(value = "/validation", method = RequestMethod.POST)
public ResponseEntity<?> acceptData(#Valid #RequestBody Data data, Errors errors,
#RequestHeader(HttpHeaders.ACCEPT_LANGUAGE) String language) {
stringValueValidator.validate(language, data, errors);
if (errors.hasErrors()) {
return new ResponseEntity<>(createErrorString(errors), HttpStatus.BAD_REQUEST);
}
return new ResponseEntity<>(HttpStatus.OK);
}
Refer this : https://blog.codecentric.de/en/2017/11/dynamic-validation-spring-boot-validation/
Here is how you can achieve to defining validations in RequestBody you are receiving from client side.
Define your POJO you will receive from client side.
public class Employee implements Serializable {
private Long id;
#NotNull(message = "Name should not be null")
#NotBlank(message = "Name should be not empty")
#Size(min = 1, max = 255, message = "Name allowed max 255 characters")
private String name;
Now in your controller use #Valid annotation for #RequestBody like below.
public ResponseEntity<?> createEmployee(#Valid #RequestBody Employee employee)
I get always null value from body why ?
I have no problem with using fiddler but postman is fail.
I have a web api like that:
[Route("api/account/GetToken/")]
[System.Web.Http.HttpPost]
public HttpResponseBody GetToken([FromBody] string value)
{
string result = value;
}
My postman data:
and header:
WebAPI is working as expected because you're telling it that you're sending this json object:
{ "username":"admin", "password":"admin" }
Then you're asking it to deserialize it as a string which is impossible since it's not a valid JSON string.
Solution 1:
If you want to receive the actual JSON as in the value of value will be:
value = "{ \"username\":\"admin\", \"password\":\"admin\" }"
then the string you need to set the body of the request in postman to is:
"{ \"username\":\"admin\", \"password\":\"admin\" }"
Solution 2 (I'm assuming this is what you want):
Create a C# object that matches the JSON so that WebAPI can deserialize it properly.
First create a class that matches your JSON:
public class Credentials
{
[JsonProperty("username")]
public string Username { get; set; }
[JsonProperty("password")]
public string Password { get; set; }
}
Then in your method use this:
[Route("api/account/GetToken/")]
[System.Web.Http.HttpPost]
public HttpResponseBody GetToken([FromBody] Credentials credentials)
{
string username = credentials.Username;
string password = credentials.Password;
}
You are posting an object and trying to bind it to a string.
Instead, create a type to represent that data:
public class Credentials
{
public string Username { get; set; }
public string Password { get; set; }
}
[Route("api/account/GetToken/")]
[System.Web.Http.HttpPost]
public HttpResponseBody GetToken([FromBody] Credentials value)
{
string result = value.Username;
}
I've been using service stack for a while and came upon a scenario where the POST method uses the default instance of the IReturn object (with all the properties defaulting to their datatype values). The values supplied as part of the Route (/product/1234345/) are the only ones populated. I've laid out an example below:
[Route("/search/{searchMethod}/books")]
public class SearchRequest : IReturn<SearchResponse>
{
public SearchProvider searchProvider { get; set; }
public string searchTerm { get; set; }
public string categoryID { get; set; }
public long maxResults { get; set; }
//Only this property gets populated if method is post
public string searchMethod { get; set; }
}
public SearchResponse Any(SearchRequest searchRequest)
{
//This works only for non-post requests
return Put(searchRequest);
}
public SearchResponse Get(SearchRequest searchRequest)
{
//This works
return Put(searchRequest);
}
public SearchResponse Post(SearchRequest searchRequest)
{
//This does not
return Put(searchRequest);
}
public SearchResponse Put(SearchRequest searchRequest)
{
//Code for put method goes here
}
I'm then using a client to call these methods
SearchServiceClient searchClient = new SearchServiceClient(SearchServiceAPIUrl);
SearchResponse searchResponse = searchClient.Search(SearchProvider.SampleSearchProvider, searchterm, categoryID, 100,"conservative");
Any help is really appreciated
Thanks
I've always just populated my request object in the constructor and sent it to the service
searchClient.Post(new SearchRequest(SearchProvider.SampleSearchProvider,
searchterm, categoryID, 100,"conservative")):
I finally found the solution after tinkering with the DTO. It seems for post requests all DTO properties needed to have a [DataMember] attribute for serialization/deserialization and make sure that the class also has a [DataContract] attribute.
This is an simple Scenario , i totally understand the first code of set & get.
private string exampleValue;
public string Example
{
get { return this.exampleValue ; }
set { this.exampleValue = value ; }
}
How is it differ from this code :
public string Example
{
get
{
return this["Example"].ToString();
}
}
It is an Indexer property.
You can define your own indexers in a class. For example, here is a string indexer.
class myClass
{
...
public object this[string name]
{
get
{
... implement code here to retrieve the object that correspond to your string index
}
set
{
... implement code here to store the object that correspond to your string index
}
}
}
Indexers are not limited to string or integer. For example, the Dictionary object uses a generic Indexer:
public class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>, ...
...
public TValue this[TKey key] { get; set; }
Also, the Session and Application objects in ASP.NET uses a string indexer.
I have a web method that accepts object
[WebMethod]
public static void GetObject(object data)
{
}
Also, I have 2 classes:
class ConnectionString
{
public string ConnectionString { get; set; }
public DatabaseType DatabaseType { get; set; }
}
class Path
{
public string Path { get; set; }
public bool IsNetwork { get; set; }
}
On client side, using javascript, i defined 2 similar classes as well:
function ConnectionString() {
this.ConnectionString = '';
this.DatabaseType = 0;
};
function Path() {
this.Path = '';
this.IsNetwork = false;
};
Now, according to user decision, he can ether choose to create log in database or file system. When I send data to the method, my object resulted as null. If I create method
for each object, it works. Is there a way to unbox or desirialize from OBJECT type to ?
You need to create two method overloads that each take in one of the possible classes. In the current implementation the engine does not know what classes should be put in the WSDL...
If you are using WCF you could use [KnownType] attribute to specify which classes your method supports.