I have the same problem as this question and tried the suggested solutions but no luck.. Any help will be very appreciated.
Bind Exclude not working Model Binding for child objects in ASP.Net MVC
The problem is as following:
I got into a issue in Model Binding in Asp.Net MVC. I have view model like below,
public class ArticleViewModel : BaseViewModel
{
public Article art { get; set; }
public List<ArticleAttachment> attachments { get; set; }
}
I am trying to exclude model binding a property on the "Article" child object as seen below in my action method,
[HttpPost]
[ValidateInput(false)]
public ActionResult New([Bind(Exclude = "art.Abstract")]ArticleViewModel articleVM)
{
But the model binder populates the property called Abstract even with the above setting.
To make this work, you need to apply the [Bind] attribute the ArticleAttachment class.
[Bind(Exclude="Abstract")]
public class ArticleAttachment
{
public string Abstract { get; set; }
....
}
However, any time you use either the [Bind(Include="..")] or [Bind(Exclude="..")] attributes, delete them and do it properly using a view model to represent what you want to edit.
Related
I'm using MVC (for the first time) with Entity framework, Database first
What I want to do is display data from a database in a single view. I created the database first, then I made a ADO.NET Entity Data Model based from the database that contains all the tables. I then created a Index view that was strongly typed with my Entity Data Model as model.
In my Index I have at the top
#model IEnumerable<Forum6.Models.Forum>
This allows me to get the rows from the table "Forum" from my database. If I try to add an extra model I get I get this error message when I run:
Line 1: #model IEnumerable<Forum6.Models.Forum>
Line 2: #model2 IEnumerable<Forum6.Models.Post>
Parser Error Message: Only one 'model' statement is allowed in a file.
After searching for an answer I found this: Two models in one view in ASP MVC 3
The answer was to create a ViewModel (ParentModel) that contained all the Models (Tables).
This is the ViewModel I created:
public class ViewModel
{
public IEnumerable<Forum6.Models.Forum> Forum { get; set; }
public IEnumerable<Forum6.Models.Post> Post { get; set; }
public IEnumerable<Forum6.Models.Topics> Topics { get; set; }
public IEnumerable<Forum6.Models.Users> Users { get; set; }
public IEnumerable<Forum6.Models.PrivMsg> PrivMsg { get; set; }
public IEnumerable<Forum6.Models.Permission> Permission { get; set; }
}
I edited my controller to look like this:
public class HomeController : Controller
{
// ForumDBEntities old_db = new ForumDBEntities();
ViewModel db = new ViewModel();
public ActionResult Index()
{
return View(db);
}
}
Then replaced the old Index view with a new strongly typed view that used the ViewModel as model. Which contains:
#model IEnumerable<Forum6.Models.ViewModel>
Trying to run this gives me this error:
The model item passed into the dictionary is of type 'Forum6.Models.ViewModel', but this dictionary requires a model item
of type
'System.Collections.Generic.IEnumerable`1[Forum6.Models.ViewModel]
How do I make the "ViewModel" enumarable? Or is my error elsewhere?
You'll need to change #model IEnumerable<Forum6.Models.ViewModel> to #model Forum6.Models.ViewModel as you're wrapping your IEnumerables inside a single ViewModel.
A good rule of thumb is to have a 1:1 relationship between your ViewModel and View.
This might be a good read for you: http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/ (just ignore the automapper part if you don't want to go that route)
You'll also need to put in actual data in your ViewModel since
ViewModel db = new ViewModel();
public ActionResult Index()
{
return View(db);
}
will just give your view an empty ViewModel.
One way to do it would be.
public ActionResult Index()
{
var model = new ViewModel
{
Forum = db.GetForum(),
Post = db.GetPost(),
Topic = you get the idea
};
return View(model);
}
One last thing when naming properties or variables in general you should use the plural verb when it contains a list. So your ViewModel would be.
public class ViewModel
{
public IEnumerable<Forum6.Models.Forum> Forums { get; set; }
public IEnumerable<Forum6.Models.Post> Posts { get; set; }
public IEnumerable<Forum6.Models.Topics> Topics { get; set; }
public IEnumerable<Forum6.Models.Users> Users { get; set; }
public IEnumerable<Forum6.Models.PrivMsg> PrivMsgs { get; set; }
public IEnumerable<Forum6.Models.Permission> Permissions { get; set; }
}
Change #model IEnumerable<Forum6.Models.ViewModel> to #model Forum6.Models.ViewModel as you are passing a single instance of a ViewModel class and not a collection of them.
All your collections are passed in a single instance of a view model.
I am reading a book on ASP.NET MVC, and it refers to "members of a view model class"? Specifically what are "members"? An example would help greatly!
Thanks!
A class member could be property, field, method, constant, event, ...
Here's an example of a view model with a property (which is a member):
public class MyViewModel
{
public string FooBar { get; set; }
}
or with a property and a method:
public class MyViewModel
{
public string FooBar { get; set; }
public string FormatTheFoo()
{
return string.Format("{0} bazinga", this.FooBar);
}
}
As far as events are concerned, well, they are indeed members, but in terms of an ASP.NET MVC view model, they are probably not something commonly used.
I got into a issue in Model Binding in Asp.Net MVC. I have view model like below,
public class ArticleViewModel : BaseViewModel
{
public Article art { get; set; }
public List<ArticleAttachment> attachments { get; set; }
}
I am trying to exclude model binding a property on the "Article" child object as seen below in my action method,
[HttpPost]
[ValidateInput(false)]
public ActionResult New([Bind(Exclude = "art.Abstract")]ArticleViewModel articleVM)
{
But the model binder populates the property called Abstract even with the above setting.
Please let me know if i am doing anything wrong. I need to exclude some of the properties in the Article child object when doing Model binding.
I'm trying to validate a model containing other objects with validation rules using the System.ComponentModel.DataAnnotations attributes was hoping the default MVC implementation would suffice:
var obj = js.Deserialize(json, objectInfo.ObjectType);
if(!TryValidateModel(obj))
{
// Handle failed model validation.
}
The object is composed of primitive types but also contains other classes which also use DataAnnotications. Like so:
public class Entry
{
[Required]
public Person Subscriber { get; set; }
[Required]
public String Company { get; set; }
}
public class Person
{
public String FirstName { get; set;}
[Required]
public String Surname { get; set; }
}
The problem is that the ASP.NET MVC validation only goes down 1 level and only evaluates the properties of the top level class, as can be read on digitallycreated.net/Blog/54/deep-inside-asp.net-mvc-2-model-metadata-and-validation.
Does anyone know an elegant solution to this? I've tried xVal, but they seem to use a non-recursive pattern (http://blog.stevensanderson.com/2009/01/10/xval-a-validation-framework-for-aspnet-mvc/).
Someone must have run into this problem before right? Nesting objects in your model doesn't seem so weird if you're designing a web service.
I suggest looking into Fluent Validation from codeplex. The validation rules are contained in a separate class (similar to the way NHibernate and Fluent NHibernate work). One uses a lambda to specify the property to validate, supporting child properties.
`
public class MaintainCompanyViewModelValidator : AbstractValidator<MaintainCompanyViewModel>
{
public MaintainCompanyViewModelValidator()
{
RuleFor(model => model.Company.ShortName)
.NotEmpty();
}
`
I have an application that have EF 16 classes that share this information: They all are classes only with a key field and a description.
I think it should be a waste if I make a controller with just 1 method just to present a form to fill these classes info, then I was thinking in to make a generic form(with key, description) and dynamically fill the right class through a sort of selection the selected info in any way, any good suggestion or pattern to do that? Where the generic methods should be located.
Have you looked into MVC templates? You should be able to use templates to automatically "generate" your Edit and Display Views. No need to create a distinct View for each of your classes.
I had similar situation and did it almost like that:
interface IKeyDescription
{
int Key { get; set; }
string Description { get; set; }
}
public partial class Class1 : IKeyDescription;
public partial class Class2 : IKeyDescription;
public abstract class BaseKeyDescriptionController<T> where T : IKeyDescription
{
[Inject]
public IKeyDescriptionService<T> Service { get; set; }
[HttpGet]
public ActionResult List()
{
//View is stored in shared folder
return View("List",Service.List());
}
[HttpPost]
public ActionResult List(IList<T> elements)
{
Service.Save(elements);
....
}
}
public class Class1Controller : BaseKeyDescriptionController<Class1>
{
}
public class Class2Controller : BaseKeyDescriptionController<Class2>
{
}
View will inherit from System.Web.Mvc.ViewPage<IKeyDescription>.