I'm fairly new to the MVC pattern and as I go deeper in developping using this logic, I'm facing some issues which I can overcome, but I am not sure if I'm doing it the proper way (best practice).
So the issue:
I have a View that receives a Model that has the following structure:
public class MyViewModel
{
public string Title { get; set; }
public string Subtitle { get; set; }
public string Property1 { get; set; }
public string Property2 { get; set; }
public string Property3 { get; set; }
public List<MyItem> ListOne { get; set; }
public List<MyItem> ListTwo { get; set; }
public List<MyItem> ListThree { get; set; }
public List<MyItem> ListFour { get; set; }
public List<MyItem> ListFive { get; set; }
}
I want the View to show the first item from each List only when the list has records in it. So what I am trying to do on the View right now is something like this:
<div>
#if(Model.ListOne != null)
{
<img src="#Html.DisplayFor(model => Model.ListOne.First().Filename)" style="max-height: 800px;max-width:800px; padding-bottom: 5px;" />
}
</div>
but when I run the code, I get an error stating System.InvalidOperationException: Sequence contains no elements. So this means, as I understand it, that the View is first fully rendered and after that the code within is parsed and converted to the final HTML output (is this how it works? could use some clarification here also)
So, what is the best way to accomplish this? Do you loose flexibility when using MVC? Right now, it feels like it. This would be so much easier to accomplish when you had your code "mixed" with the HTML. Don't get me wrong, it is very clear to me the advantadges that using design patterns bring to a developer, but for this particular problem, it is really making me wonder about how flexible it actually is.
Razor is rendering this in a single pass from the point of view of your model, and you can freely mix code with HTML - that's what makes it so awesome!
The problem here seems to be the way you are trying to access the list.
Try changing this:
#if(Model.ListOne != null)
to this:
#if(Model.ListOne.Any())
At the moment you are only checking that Model.ListOne isn't null - i.e hasn't been initialised at some point in your model via ListOne=new List<MyItem>() or something similar - but what you really need to check is if Model.ListOne is empty or not.
I'd say that you should try to make sure as far as possible that you don't have null model properties when writing your view, it makes it very messy to have to mix in null checks; better to ensure that any model property you want to access in your view is intialised before you give the model to the view.
Related
I've googled some around the internet and found some articles about the subject, but none of them satisfied me. I want to know is it good to use object-object mapper to map objects to each other? I know it depends on situation to use, but how will I realize a good or best situation to use?
Taking a step back, it's best practice to separate data transfer objects (DTOs) and view models (VMs) from business objects (entities and alike). Mapping libraries, in that regard, are a means to an end and simply make that association easier.
As far as when, that's up to you. If you feel like you can convert between your business models and DTO/VMs in a way that's easy to maintain, go ahead. From my personal experience, that only goes so far (especially as the requirements change). Therefore, I'm fond of mapping libraries (specifically AutoMapper as I've come to know it's API and am comfortable plugging it in).
Having said that, any time I have to go between these two models I use AutoMapper. I simply configure it once and I'm off and running. Additional tweaks to the models (on either side) then become easier as I can change those bindings in one place (map definition file) and methods automatically "catch up".
Example:
My database contains a Record for a product:
class Product
{
public int Id { get; set; }
public string Description { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public int QuantityOnHand { get; set; }
public int? ReorderQuantity { get; set; }
public string Sku { get; set; }
}
I may present this to the UI in a more distilled format:
public class ProductViewModel
{
public int Id { get; set; }
public string Description { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public int Quantity { get; set; }
}
If this came from a repository of some kind, I'm simply calling:
var model = Mapper.Map<ProductViewModel>(productFromRepository)
Here I consistently get the view model I care about from the Product I've requested. If the business/service layer were to add/change/remove properties, I'd only go back to my Mapper.CreateMap<Product, ProductViewModel>() defintion, but the rest of my presentation logic would remain in-tact.
In addition to #Brad Christie's answer, automapping types which have minor differences into a single overarching type is generally easier if you are meaning to display them on your view alongside other products that are generated different ways.
If you'll allow me to crib off one my own previous answers, here's an example:
class SingleProduct {
string Name {get;set;}
decimal Price {get;set;}
decimal GetActualPrice() { return Price; }
}
class ComboSaleProduct {
string Name {get;set;}
List<SingleProduct> ComboProducts {get;set;}
decimal GetActualPrice() { return ComboProducts.Sum(p => p.GetActualPrice()); }
}
class ProductViewModel {
string Name {get;set;}
decimal ActualPrice {get;set;}
}
Automapper wires everything together so that you can return either of these and it will automatically map the "GetActualPrice" to ActualPrice on your viewmodel.
So we use DataAnnotations to achieve input validation for our ASP.NET MVC forms. If we were to start again I'd consider Fluent Validation, but we're too far along now to make the change.
So this project requires us to build a lot of forms. As we've progressed, we've identified groups of inputs that get repeated across forms. An example of this might be a set of inputs to represent an Address.
We've then turned the Address input into a reusable module by creating an _AddressEntry partial view for it along with an associated view model - AddressViewModel. The view model for the parent form then looks like:
public class SubmitEnquiryViewModel
{
public AddressViewModel Address { get; set; }
public string Enquiry { get; set; }
...
}
In the _SubmitEnquiry view, we then insert the _AddressEntry partial view using EditorFor().
This works fine until we realise different instances of the Address input have different validation requirements - the validation attributes decorating AddressViewModel do not always apply. To get around the problem we define an IAddressViewModel:
public interface IAddressViewModel
{
string LineOne { get; set; }
string LineTwo { get; set; }
...
}
And then define concrete implementations of this interface for all the different permutations of validation specification - e.g. AddressViewModel (default validation), AddressNoValidationViewModel etc.
The _AddressEntry partial view is then bound to IAddressViewModel and the appropriate concrete implementation is chosen for the Address property of the parent view model.
The main drawback of this approach is that we could potentially end up with quite a few view models that only differ by the validation attributes applied to them. This is deemed acceptable though as the number of reusable modules is expected to be relatively small.
Has anyone else faced this challenge before? What solution did you come up with? What are your thoughts on the solution described above?
You may want to look into the MetadataTypeAttribute.
Base class:
public abstract class AddressDetailsBase
{
public string Line1 { get; set; }
public string Line2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public int PostalCode { get; set;}
}
Validation (I use interfaces so it can't be accidentally instantiated):
public interface IUserAddressDetailsValidation
{
[required]
string Line1 { get; set; }
[required]
string Line2 { get; set; }
[required]
string City { get; set; }
[required]
string State { get; set; }
[required]
int PostalCode { get; set;}
}
View Model Type:
[MetadataType(typeof(IUserAddressDetailsValidation))]
public class UserAddressDetails : AddressDetailsBase { }
Data Annotations are good for very simple scenarios and for prototype projects.
As you can see, you are already fighting the annotations, which are not suited to work in different contexts.
Just use plain ModelState.AddModelError in controller actions, and build custom validation logic in your controller.
ModelState.AddModelError("Prop", "Your custom 'validation failed' message.");
You can still evaluate ModelState.IsValid before doing your custom validation, so you can still use DataAnnotations for simple cases for some code reuse.
I'm new in Asp.net MVC pattern. I used to develop website using asp.net web forms. I did research for hours about MVC and got a little understanding. But there're still some problems that keep confusing me.
(I decided to use Code First)
I have to display some pretty complex data, for my old project, i was using Stored Procedure, now i think i'm gonna change to LINQ, the questions are :
Does it affect the performance ? I was having good performance with SP.
How do i "define" the objects created by the query (in this case is the result set), should i define it in model classes ?
To be more specific, this is how i get things done in my old project, i have a class called ReportData (please note this is a mini-version, the actual class contains more properties) :
public class ReportData
{
public string CityID { set; get; }
public DateTime ResultDate { set; get; }
/// ...
// free fields
public int INT1 { set; get; }
public int INT2 { set; get; }
public int INT3 { set; get; }
public int INT4 { set; get; }
public string STR1{ set; get; }
public string STR2 { set; get; }
public string STR3 { set; get; }
public string STR4 { set; get; }
}
And everytime a Stored Procedure is executed, i put the result into this class, and build the HTML markup from this class :
foreach (ReportData r in listReportData)
{
// build html markup here
}
This way i can save a whole lot of works, i don't have to write code twice for any "same same" results. And it's running ok, but i have to change due to some circumstances.
Now when stepping into MVC world, i found it very confused and honestly i'm now lost with the controlers, models, and views stuffs.
I also read about some related topic which pops up when i was typing this question, but they seem doesn't help me much in my case, oh i'm too nerd to understand the answers!
I have an MVC app using EF code first. I add a user to the system and enter pension details, part of this is a dropdown linked to a model called PensionBenefitLevel. This is the model -
[Key]
public int PensionBenefitLevelID { get; set; }
public string DisplayText { get; set; }
public int EmployeePercentage { get; set; }
public int EmployerPercentage { get; set; }
public virtual ICollection<Pension> Pension { get; set; }
When registered I have the PensionBenefitLevelID that came from the dropdown, but in my controller I was to peform a calculation using the EmployerPercentage value that is related to that ID. Can anyone point me in the correct direction?
Do I need to create a variable in the controller and use a linq query to get that value back? I've not been able to find any examples of something similar so if you could point me to one that would be great too.
If I understand the question correctly, you want to get back the entity corresponding to PensionBenefitLevelID and perform a calculation on the EmployerPercentage field.
Since you haven't mentioned what pattern you are using with EF (repository, unit of work, etc.) I can only give you a general answer:
var entity = [Your DB Context].[Your Entity].GetById(pensionBenefitLevelID);
if(entity != null)
{
[Calculation]
}
This is somewhat a two-part question (please let me know if they should be split up).
1) I have a model class with an array of objects contained inside it. I would like to be able to bind this automatically so I can accept a single pollModel argument in my controllers.
public class pollResponseModel
{
public long id { get; set; }
public long pollID { get; set; }
public string text { get; set; }
public long count { get; set; }
}
public class pollModel
{
public long id;
public long entID { get; set; }
public string question { get; set; }
public DateTime posted { get; set; }
public DateTime expiration { get; set; }
public pollResponseModel[] responses { get; set; }
}
The problem is that I'm not sure how to bind the responses field, seeing as it can be any arbitrary size. Well, I can bind it properly when displaying the edit view, but that's about it. That leads me to the second part of my question:
2) What's an acceptable way of dynamically creating and removing data in a list on the client, so that it can be bound to a model and accessed in its modified form on the server? I envision the creation/removal process working like the iPhone list GUI: a single + button will add a new element, and a - button on each row of data will remove it from the list. I would imagine jQuery is an appropriate starting point but my JS skills are very limited.
Check out this article by Phil Haack : Model Binding To a List. It explains exactly what you need to do to bind to list properties, or properties that are complex objects.
Essentially you just have to construct your POST data in the correct way for the model binder to parse it. The article explains how to add hidden index fields and represent your complex properties in your form.