How to bypass validation when using viewmodels for search filtering in ASP.NET MVC (3RC2) - validation

I'm working on an ASP.NET MVC app (using MVC3 RC2). Say I have 2 entities, Product and Category. A Category must have a CategoryTitle, which is denoted via metamodel attributes like so:
public class CategoryModel
{
public int CategoryID { get; set; }
[Required("{0} is required.")]
public int CategoryTitle { get; set; }
}
There is also a relationship such that each Product has an association with Category. When searching Products, users must be able to filter the results by selecting a Category from a drop-down HTML select list. I've tried different ways of doing this, and the following seems to promote the most code reuse:
public class SearchModel
{
public CategoryModel Category { get; set; }
public string Keyword { get; set; }
}
public class ProductController
{
public ActionResult Search(SearchModel searchModel)
{
if (ModelState.IsValid)
{
// logic to return view with viewmodel
}
return HttpNotFound();
}
}
In the view, a drop-down list is rendered using the SearchModel, and it sends requests via HTTP GET in the form of /Product/Search?Keyword=my+keywords&Category.CategoryID=69. The SearchModel object is populated as intended, creating a new CategoryModel with CategoryID == 69.
The problem is that the ModelState.IsValid always returns false, since the Category.Title is null. What is the appropriate way to do this in ASP.NET MVC? Do I have to resort to creating a different SearchModel that doesn't have a CategoryModel instance?

The proper way to do this is to use view models instead of your models to and from the views. View models are classes which are specifically tailored to the needs of a given view: they contain only the properties required for the view and the validation attributes in the context of the given view. Thus you might have multiple view models for the same model. To map between the model and the view models you could use AutoMapper.

Related

Can Mvc EditorFor Collection Order Be Reversed?

I am using Mvc 3 and have come across the following scenario:
I've got a view model that has a list of note elemements as a property and I am using the HtmlHelper extension method EditorFor to render out the collection. All is working great. However now I need to display the note elements in the reverse order.
Is there a way to tell Mvc to reverse the elements?
// View Models
public class MyViewModel
{
public List<Note> Notes
{
get;
set;
}
}
public class Note
{
public string Username
{
get;
set;
}
public DateTime ChangedDate
{
get;
set;
}
public string Text
{
get;
set;
}
}
The elements are in oldest first order.
I can reverse the order of the elements in the collection to solve the problem which at the moments seems the most logically way to go. However that makes the javascript to insert new notes more complex as that requires the name and id of the html elements to be rewritten.
So I was hoping there maybe some sort of order option for the EditorFor method.
Another alternate would be to write a custom partial view and update the TemplateInfo.HtmlFieldPrefix but I like to keep to using the EditorTemplates if I can.

How to make single controller for two database classes - MVC3

I have two database classes as defined below:
public class TopDate
{
[Key]
public int DateId { get; set; }
public DateTime Date { get; set; }
}
public class TopSong
{
[Key]
public int SongId { get; set; }
public string Title { get; set; }
public int DateId { get; set; }
}
where DateId is foreign key to TopSong
I am creating a controller through which i can create, delete or edit these database values.
When i right click on controller class and add controller i can only select one of the two classes defined above. Is there a way to make 1 controller to handle database updates to both these tables on one page?
Error Image:
Your controller should not be dealing directly with domain objects (meaning those things that are directly associated with your database). Create a ViewModel that contains the properties that you need, use your service layer to populate the ViewModel and your controller will use that as the Model for its base. An example of your ViewModel could be something like the following given your description above:
public class MusicViewModel
{
public int SongId {get;set;}
public string Title {get;set;}
public IEnumerable<DateTime> TopDates {get;set;}
}
This view model would contain a list of all dates that a specific song was a Top Song.
The objects you showing (code) are database classes (so called domain objects).
What you need to do is to define a view model, a standard ASP MVC practice:
you define a class, that is tailored for specific view and only containing data relevant to that particular view. So you will have a view model for a view that will create a song, another that will update it etc.
Actually situation you describing is classical situation to use view models. Using domain objects in the views, however, is really really bad practice and prone to more problems than you want to deal with.
Hope this helps.

Giving error while creating partial class

I am developing MVC application in which , I am trying to create the partial class of class generated by MVC application lets say Location class.
Now I want to create the partial class of Location class in new class file.
The below class code is auto genrated by MVC of Location code.
namespace CRM
{
public partial class Location
{
public int Id { get; set; }
public string Name { get; set; }
public string Remark { get; set; }
}
}
I have added new class file which contain the partial class of above file
namespace CRMEntities.Partial_Class
{
public interface ILocation
{
[StringLength(50, ErrorMessage = "Region can accept maximum 50 characters.")]
string Region { get; set; }
[Key]
int Id { get; set; }
[Required]
string Name { get; set; }
string Remark { get; set; }
}
public partial class Location : ILocation
{
}
}
Its giving the below error...
CRMEntities.Partial_Class.Location' does not implement interface member 'CRMEntities.Partial_Class.ILocation.Name
First, you don't need to do this, what I understand is you are trying to do validation right? Think about, the object generated by EF is not ViewModel, they are domain model. Data annotation should be in View Model, not domain model.
Most of cases, often mis-use is to use domain model as view model, but it is not correct much. Because sometime, view models need more than one domain model to provide data for your UI.
So for separation of concerns, you need to define your View Model different with domain model.
Example: you have Location class, you need to add LocationViewModel class and put data annotation in here.
You can map manually or use AutoMapper for mapping bettween View Model and Domain Model.
Another solution is you can use Fluent Validation, with this way, needless to have more partial class just for validation.
You don't show the definition of ILocation in your question, but the error says that the Location.Name property is declared differently than the ILocation.Name member.
Edit: Your two partial classes appear to be in two different namespaces, hence they are actually two entirely different classes, not two parts of the same class. That would explain the compiler error.
Having said that, I do agree with the other answer (+1!) that you should do your UI validation on a view model instead.

Using different two ado.net entity models in a one view at MVC3

How can i use two different ado.net entity in one view at MVC3 ?
You can create a model that encapsulates both entities.
public class MyViewModel
{
public AdoEntityA { get; set; }
public AdoEntityB { get; set; }
}
Alternatively, you could create a view model that only holds the specific fields you need from the two entities.
Automapper is very useful mapping between domain entities and view models.

ASP.NET 4.3 Scaffolding: Add Controller vs Add View - different behavior?

I am trying to dig into ASP.NET MVC 3, using the standard tutorials in the web, and I encounter a strage problem.
Currently, I am following the samples in a book, using a "Movie" class with movie genres stored in a separate entity, connected with a foreign key (okay, I am from Germany, so my class is named in German). I show only the relevant properties here. It's a database first approach using DbContext, my model was created from the edmx by using the EF 4.x DbContext Generator and the edmx was automatically created from the data base.
public partial class Film
{
public Film() { }
public int ID { get; set; }
public string Titel { get; set; }
public int GenreID { get; set; }
public virtual Genre Genre { get; set; }
}
public partial class Genre
{
public Genre() { }
public int GenreID { get; set; }
public string Name { get; set; }
}
When I create a new Controller with CRUD Views for the Film class, using a DBContext that provides a DBSet, I get an Edit view that uses a DropdownList to edit GenreID, labelled "Genre". Fine. That's what I want.
But then, I tried to create another edit view, separately. So I right-clicked into my Edit Action-Method, selected "Add View", called it "Edit2", used Film as model and "Edit" as scaffold template. In this view, I got a simple "EditorFor(m->m.GenreID)", labelled GenreID. That's not what I want.
Of course, I can change that manually. Of course, I can download a slew of scaffolding tools that claim to do better.
But I want to understand if this is a bug in the EF templates, or if my model is built wrong so that Genre / GenreID gets confused. When I create everything at once, scaffolding creates a DropDown, so there must be "just" some detail that's missing.
You will need to call your Action in your controller "Edit2".

Resources