patterncsharpMinor
View Model Constructor Arguments
Viewed 0 times
constructormodelviewarguments
Problem
I have created a ViewModel for a Product Edit page because it has specific related entities I need to load - the class currently looks like this:
So then in my controller I can go:
I've not really seen anybody do it like this though, is it bad practice - and for what reason? What are the better alternatives to accomplish this if this is wrong?
public class ProductEditView
{
public ProductEditView(Product product)
{
this.ID = product.ID;
this.Code = product.Code;
this.ProductLanguage = product.ProductLanguages.Where(x => x.LanguageID == Global.Language).FirstOrDefault();
this.PrimaProduct = product.PrimaProduct;
this.Multimedias = product.Multimedias;
}
public int ID { get; set; }
public string Code { get; set; }
public ProductLanguage ProductLanguage { get; set; }
public PrimaProduct PrimaProduct { get; set; }
public IEnumerable Multimedias { get; set; }
}So then in my controller I can go:
public ActionResult Edit(int? id)
{
if (id == null) return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
Product product = db.Products.Find(id);
if (product == null) return HttpNotFound();
ProductEditView productEditView = new ProductEditView(product);
return View(productEditView);
}I've not really seen anybody do it like this though, is it bad practice - and for what reason? What are the better alternatives to accomplish this if this is wrong?
Solution
Its a very tight coupling between HTTP and your domain.
However I do not like classic layered architecture. I often utilizes CQS for my service API's
Your example would look like
You can then translate the errors into HTTP codes using a Exception filter, here is an example from my current project
However I do not like classic layered architecture. I often utilizes CQS for my service API's
Your example would look like
public class GetProductQueryHandler: IQueryHandler
{
private readonly DbContext db;
public GetProductQueryHandler(DbContext db) {
this.db = db;
}
public async Task Handle(GetProductQuerycommand query) {
if (!query.Id.HasValue) throw new ArgumentExpection("Id is required"); //Not accepting null for a Nullable is a bit strange
var product = await db.Products.FindAsync(id);
if (product == null) throw new NotFoundExcpetion("Product");
return product;
}
}You can then translate the errors into HTTP codes using a Exception filter, here is an example from my current project
public class ExceptionFilter : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
base.OnException(actionExecutedContext);
var message = "Server error";
var details = "Please contact support if the problem persists";
var code = HttpStatusCode.InternalServerError;
if(actionExecutedContext.Exception is ArgumentException)
{
code = HttpStatusCode.BadRequest;
message = "Bad Arguments";
details = actionExecutedContext.Exception.Message;
}
#if DEBUG
details = string.Format("{0}: {1}", actionExecutedContext.Exception.Message, actionExecutedContext.Exception.StackTrace);
#endif
var response = new
{
Message = message,
Details = details
};
actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(code, response);
}
}Code Snippets
public class GetProductQueryHandler: IQueryHandler<GetProductQuery, Product>
{
private readonly DbContext db;
public GetProductQueryHandler(DbContext db) {
this.db = db;
}
public async Task<Product> Handle(GetProductQuerycommand query) {
if (!query.Id.HasValue) throw new ArgumentExpection("Id is required"); //Not accepting null for a Nullable is a bit strange
var product = await db.Products.FindAsync(id);
if (product == null) throw new NotFoundExcpetion("Product");
return product;
}
}public class ExceptionFilter : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
base.OnException(actionExecutedContext);
var message = "Server error";
var details = "Please contact support if the problem persists";
var code = HttpStatusCode.InternalServerError;
if(actionExecutedContext.Exception is ArgumentException)
{
code = HttpStatusCode.BadRequest;
message = "Bad Arguments";
details = actionExecutedContext.Exception.Message;
}
#if DEBUG
details = string.Format("{0}: {1}", actionExecutedContext.Exception.Message, actionExecutedContext.Exception.StackTrace);
#endif
var response = new
{
Message = message,
Details = details
};
actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(code, response);
}
}Context
StackExchange Code Review Q#109624, answer score: 2
Revisions (0)
No revisions yet.