What is the best practices to pass data from presentation to application layer?
Currently I have something like this:
in presentation layer:
the controller:
public class ProductController : Controller
{
private readonly IProductService _productService;
public ProductController(IProductService productService)
{
_productService = productService;
}
public ActionResult ProductCreateAction(ProductCreateViewModel vm)
{
_productService.CreateProduct(vm);
return Json(new { Ok = true });
}
}
and the view model:
public class ProductCreateViewModel : ICreateProductCommand
{
public string Name { get; set; }
public int Price { get; set; }
}
in application layer:
public class ProductService : IProductService
{
public void Create(ICreateProductCommand command)
{
var product = new Product(command.Name, command.Price);
//... add to repositoey and call SaveChanges ...
}
}
public interface ICreateProductCommand
{
string Name { get; set; }
int Price { get; set; }
}
(using FluentValidation
here)
public class CreateProductCommandValidator : AbstractValidator<ICreateProductCommand>
{
public CreateProductCommandValidator()
{
RuleFor(x => x.Name)
.NotEmpty();
RuleFor(x => x.Price)
.NotEmpty();
}
}
- Is it ok to continue using this approach or there are better practices?
- Is it better to have one save action in controller or separate create/update actions?
i.e.:
public ActionResult Save(SomeViewModel vm)
{
if(vm.Id.HasValue)
{
//update
}
else
{
//create
}
}
vs.
public ActionResult Create(SomeViewModel vm)
{
//create
}
public ActionResult Update(SomeViewModel vm)
{
//update
}
1 Answer 1
Overall, your code is very good, there is not much to review..
In your ViewModel, you might want to use DataAnnotations
to do client (using jquery unobstrusive script)/server validation ex :
public class ProductCreateViewModel : ICreateProductCommand
{
[Required]
public string Name { get; set; }
[Required]
public int Price { get; set; }
}
public ActionResult ProductCreateAction(ProductCreateViewModel vm)
{
if(ModelState.IsValid) //Server validation of the data annotations.
{
_productService.CreateProduct(vm);
return Json(new { Ok = true });
}
}
To answer your second question, I believe it is better to use two separated actions to separate the use cases of when you will use Create vs. Update. Plus one day you might have different roles for adding and updating (it's a little hardcore but it could happen), you would want your actions to be marked with different authentication attributes (If you use MVC membership)