I have a WebAPI POST controller like the one below:
[ResponseType(typeof(Product))]
public async Task<IHttpActionResult> PostProduct(Product product)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Products.Add(product);
await db.SaveChangesAsync();
return CreatedAtRoute("DefaultApi", new { id = product.Id }, product);
}
To be valid, it expects several values, lets say Name, Price, URL, ManufactureID, StatusID.
However, the POST will not always contain a value for StatusID for example, and therefore the above will fail, as i cannot be null.
But when the value is not sent by the POST, i want to 'intercept' and set the value in code. Let say to int 1.
How would i go about this?
I have been using DTOes for extraxting data from the API, in a nice and viewable way. Can DToes be used in POST also? If so, how? Or any other approach, to setting data, if it does not excist in the POST?
I would say create your Product request model which will be defined in your WebAPI models and there your can define your StatusID as a nullable. After your receive request you can map your Product request data to ProductDto and in that mapping you set your default values if you need them.
Altough you can intercept request on client side and update it but I'm not sure is that something that will work for you.
You should create a POST product class that is agnostic of the persistence. Don't use the generated Product class of your ORM. Using your example above, you should have a ProductModel class that will only contain the properties that the API client can update. Then do the mapping of the DTO to your product data model.
public async Task<IHttpActionResult> PostProduct(ProductModel model)
{
...
var product = db.Products.New();
//mapping here
product.Name = model.Name;
product.Price = model.Price;
}
Related
1. For example UserProfile which has 3 properties name,dob, age
2. And 2nd class let's say UserProfileResponse which has only "id"
public ResponseEntity<UserProfileResponse> createUserProfile(#RequestBody UserProfile userProfile)
{
UserProfileResponse userProfileResponse = new UserProfileResponse();
userProfileResponse.setId(??) // How do I set ID?
**createUserProfileData(userProfile) /// This is used to create DB record**
return new ResponseEntity<UserProfileResponse>(userProfileResponse,HTTPStatus.OK);
}
So for this userProfileResponse.setId(??) how can I set the ID value?
can I directly do like this userProfileResponse.setId(userProfileResponse.getId());
Or I can Pass one more request body like this
ResponseEntity<UserProfileResponse> createUserProfile(#RequestBody UserProfile userProfile, #RequestBody ID)
Thanks in advance.
You can call createUserProfileData method and return the id of the newly inserted object from it.
In createUserProfileData method, you can call saveAndFlush method of the repository which will save the userProfile Object.
This will return the id of the newly inserted object.
Finally your code will look like below:
public ResponseEntity<UserProfileResponse> createUserProfile(#RequestBody UserProfile userProfile)
{
UserProfileResponse userProfileResponse = new UserProfileResponse();
int id = createUserProfileData(userProfile)
userProfileResponse.setId(id)
return new ResponseEntity<UserProfileResponse>(userProfileResponse,HTTPStatus.OK);
}
If you want to get a value from the RequestBody UserProfile which it didn't contain it actually.Sorry it's impossible.
And we only could receive one requestBody at one time,so we need to use some other ways to collect the info.There is some other solutions:
Use #PathVariable to get ID from url
Use #RequestParam to get Id from requestParam
Add a new field named Id into your UserProfile
Use other way that that could get your Id,this depend how you persistent or generate the Id.
In your case,I'm not sure what you are going to do with the id.
If the "createUserProfileData" method means you need to offer an id first for persistence.
Well,I dont know which database and what kind of framework you are using.As I know,most of framework and database has the ability to generate the id automatically.But if you insist to generate id by your self,I recommend you UUID.
If the "createUserProfileData" method is saving the UserProfile to the database literally and the id is generated by the database itself,then you just do it and put the Id represent the record you just saved to UserProfileResponse.
As to how to get the id represent the record you just saved?It's up to the framework you're using and precisely how the code is written.
I have a ViewModel used in a Web API web service.
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
Then I have an ApiController with a method like this:
[Route("api/Customer/{Id}")]
public IHttpActionResult Post(int Id, [FromBody]Customer Customer)
{
...Add to db, Id also exists in Customer
return Ok();
}
Customer Id is available in the URI - but the Customer object contains a Customer Id - which could be passed into the Post.
This seems to be redundant - and may lead to the Id being put in the wrong place.
What is best practice? If I need to remove Id from Customer body how do I do it?
Reference - "Using HTTP Verbs with the Task Resource" - level 2 in the REST Maturity Model - states the Id should be passed in the URI for updating or inserting tasks with an Id:
Generally we call a POST method when we try to create a new record, in your case "Customer" and PUT method to update an existing record. But that is not mandatory. You can create and update an existing record by using POST method too.
In general, we set auto generated field to the Id (primary key) field of a table. That means, we don't need to pass data for Id field when we try to add a record. In that case you don't need to pass Id in your URI and you don't need to write a parameter for Id in your API POST method.
So your ajax method will be like this bellow,
$.ajax({
url: 'myURL',
type: "json",
contentType: 'application/json; charset=utf-8',
data: myFormData,
success: function(data)
{
alert("success");
}
})
As I mentioned above you can use the same method (POST) for add a new record or edit an existing record, so how is that possible ?
I assume you are passing Id value in your ajax code in data parameter.
So your API Post method will be like this,
[Route("api/Customer")] // I removed Id here
public IHttpActionResult Post([FromBody]Customer Customer)
{
if(Customer!=null && Customer.Id==0) //You can check Id with null value
{
// Add a new record to Customer
}
else
{
// fetch Customer data by Customer.Id and update here
}
return Ok();
}
As simple as that. But yes, you can write this update code in a PUT method.
But if you are passing value to the Id field(that is not auto generated field) in POST method, then also you can remove the Id parameter from your POST method and your Route will be like this,
[Route("api/Customer")]
Hope it helps :)
My normal Post params looks like this:
public Product Foo([FromBody] Product item)
{
// ...do something
return item;
}
But I keep seeing many samples on the net where the Post method does not have the [FromBody]:
public Product Foo(Product item)
{
// ...do something
return item;
}
Is there a difference between these two methods?
Can they be called the same way from the client?
You only need [FromBody] when you post a simple type, like an int. The model binder automatically looks for complex types in the request body.
In your example you don't need [FromBody], as Product is a complex type.
I am working with a Spring MVC project and I can't figure out how to change the String representation of a Model in the Views.
I have a Customer model that has a ONE_TO_MANY relationship with a WorkOrder model. On the workorders/show.jspx the Customer is displayed as a String that is the first and last name, email address, and phone number concatenated.
How do I change this? I thought I could just change the toString method on the Customer, but that didn't work.
One solution would be to change/push-in show() to WorkOrderController to map a rendered-view-tag to what you would like to see.
#RequestMapping(value = "/{id}", produces = "text/html")
public String show(
#PathVariable("id") Long id,
Model uiModel)
{
final WorkOrder workOrder = WorkOrder.findWorkOrder(id);
uiModel.addAttribute("workOrder", workOrder);
uiModel.addAttribute("itemId", id);
// Everything but this next line is just ripped out from the aspectJ/roo stuff.
// Write a method that returns a formatted string for the customer name,
// and a customer accessor for WorkOrder.
uiModel.addAttribute("customerDisplay", workOrder.getCustomer().getDisplayName());
return "workorders/show";
}
Put/define a label in your i18n/application.properties file for customerDisplay.
Then in your show.jspx, you can access the mapping with something like... (The trick is similar for other views.)
<field:display field="customerDisplay" id="s_your_package_path_model_WorkOrder_customerDisplay" object="${workorder}" z="user-managed" />
I'm new to Roo, so I'd love to see a better answer.
We found a good solution. There are toString() methods for all the models in ApplicationConversionServiceFactoryBean_Roo_ConversionService.aj
You can just push the method for the Model you want into ApplicationConversionServiceFactoryBean.java and modify it. In my case I added this:
public Converter<Customer, String> getCustomerToStringConverter() {
return new org.springframework.core.convert.converter.Converter<com.eg.egmedia.bizapp.model.Customer, java.lang.String>() {
public String convert(Customer customer) {
return new StringBuilder().append(customer.getId()).append(' ').append(customer.getFirstName()).append(' ').append(customer.getLastName()).toString();
}
};
}
Spring uses this for all the view pages so this will change the String representation of your model across your whole app!
I have what is probably a basic question regarding how to structure an MVC page.
Assume this is my model:
public class MyModel
{
int ProductId
List<ParameterTable> ParameterTables
...
[other properties]
...
}
ProductId initially won't have a value, but when its value is selected from a DropDownList it will trigger an event that retrieves the List items associated with that product.
My problem is when I do this AJAX call to get the parameter tables I'm not sure how to handle the response. I've only seen examples where people then manually inserted this data into the page via the jquery. This would mean handling displaying the data in your view (for the first time loading the page) and in the jquery (whenever it changes).
I am wondering if there's a way to somehow pass back a model of sorts that binds my return value of List into my page without needing to specify what to do with each value.
Would I have to have the changing of the ProductId DropDownList trigger an ActionResult that would reload the whole page to do this instead of a JsonResult?
You could return a partial view with your ajax call.
Controller action:
public ActionResult Filter(int productId) {
var product = _repository.Find(productId);
if (Request.IsAjaxRequest())
{
return PartialView("_Product", product);
}
else
{
return View(product);
}
}