ASP.net MVC create model with value with multiple options - asp.net

I am wanting to create a Model that has a property of Service which then has multiple options that can either be true or false. So my Contact Class:
public class Contact
{
//My Properties
}
I want the Contact class to have a property of Services. I have a list of services available. How can I reference my services from my Contact class. I would like be able to access it in my view like: model.services.MyCustomService if it's even possible. I come from a javascript background so this is what I mean but written in javascript if it helps.
Javascript Example
var Contact = {
property: "",
services: {
MyCustomService: "",
MyCustomService2: "",
}
}

Here's how I'd do it:
In your Model:
public class Contact
{
//My Properties
public List<Service> Services
{
get;
set;
}
}
In your Controller:
public ActionResult Index()
{
var model = new Contact(); // Create model
// Create some sample services
var service = new Service();
var service2 = new Service();
// Add the services
model.Services.Add(service);
model.Services.Add(service2);
// Pass the model to the view
return View(model);
}
Then, in your view:
#model MySite.Models.Contact
#foreach (var service in Model.Services)
{
<text>Here's my service: #service.MyCoolProperty.ToString()</text>
}
In that simple example, I first declared the Services property of your Contact class as a List<Service>. That allows you to combine many Services into one property - perfect for passing along to a view.
Next, in the Controller, I added some Services to the List by using the Add() method. Therefore, in the View, you're now able to access those Services through Model.Services.
To me, that looks like one of the simplest ways to approach this common problem. Hope that helped!

In C#, every object has a type so Services property has to have an actual type if you want to reference MyCustomService and MyCustomService2 through dot notation:
class Contact {
public ServiceContainer Services { get; set; }
}
class ServiceContainer {
public Service1 Service1 { get; set; }
public Service2 Service2 { get; set; }
}
However, if container serves for no other purpose but to store a service (assuming it's some object), you should probably store them in a list or array (access by index) or in a dictionary (access by string).
To give you more information, I'll need to know what exactly these services are, whether you expect their set to change, do they have different types, etc.

To bind to a collection all you need is this:
<%# Page Inherits="ViewPage<IList<Book>>" %>
A complete explanation can be found here:
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

Related

When to use BindAttribute?

I'm learning asp.net mvc and wonder when we need to use BindAttribute.
The first case (using Bind):
Model:
public class Book
{
public string Id { get; set; }
public string Name { get; set; }
public string Author { get; set; }
}
Controller:
public IActionResult Create([Bind(nameof(Book.Name), nameof(Book.Author))] Book model)
{
return Ok();
}
The book Id would be generated on server side. So, client side has nothing to do with it, every actions try to change/make the id is prevented.
The second case (not using Bind):
Model:
public class BookViewModel
{
public string Name { get; set; }
public string Author { get; set; }
}
Controller:
public IActionResult Create(BookViewModel model)
{
return Ok();
}
Because the second model doesn't contain Id property, we don't need to prevent from creating or changing.
I prefer the second. It's easy to manage model.
Is there a case we must use Bind attribute?
We use bind when we want that some properties of complex property are ignored when received on server. It could be for safety or other reasons.
When this action is executed the MVC model binder will use the request parameters to populate the user parameter's properties, as you may already know. However, the Bind attribute tells the model binder to only populate properties with names specified.
So in this case only the Username, FullName and Email properties will be populated. All others will be ignored.
See here for more details: http://ittecture.wordpress.com/2009/05/01/tip-of-the-day-199-asp-net-mvc-defining-model-binding-explicitly/
If you have situation when you only have to ignore one parametar from binding you could use Exclude property:
[Exclude]
public Entity Name {get; set;}
Bind is used to increase security and unauthorized data to be posted on server . In your model class , suppose you have content property also. if the content property is not needed in the future. Then it would be difficult for you to remove all the occurrences of that property. Here you can use bind property like this
[Bind(exclude="content")]
or you can bind only selected properties to be posted on server by including the properties like this
public ActionResult create([Bind(Include = "Name,Author")] Modelclass modelclass)
{
//Do something here
}
You can learn more about it here
Second approach is more suitable instead writing all the properties and bind them but there are some situations where you must bind user like you have a roles property or IsAdmin property in your model then you might not want that user somehow posts the IsAdmin or roles properties to the server . That's where you can use Bind attribute

ASP.Net Model without DbContext?

I am new to ASP.Net, if my question sounds very basic, please be polite.
I have created a ASP.Net MVC4 project. A page in the application will display names of the files in tabular form.
The names of the files are obtained by finding files in a particular folder on the server. So there is no need for me to have a database for model.
When user opens the page, the server side code will list all the files in the directory and should return a list of Strings.
I am following ASP.Net MVC tutorial here and it appears I have to have a DBContext class and also a database. In my case that's not needed
So that question is can I add my model without having to add code like below and still be able to use the feature of model ? any simple example would be great.
public class MovieDBContext : DbContext
{
public DbSet<Movie> Movies { get; set; }
}
Any class can serve as a model in this case. For example, if you just want to have a Movie model, you can have something as simple as this:
public class Movie
{
public string Title { get; set; }
}
A view can bind to that model, to an enumeration of that model, etc.
For fetching your data from the file system, one approach could be a simple factory method on that model. Maybe something like this:
public class Movie
{
public string Title { get; set; }
public static IEnumerable<Movie> GetMovies()
{
// get the list of movies from the file system, for example as a list of strings
var movies = SomeFileSystemInteraction();
return movies.Select(m => new Movie { Title = m });
}
}
Then in your controller you can get the list of movies to bind to the view:
public ActionResult Index()
{
return View(Movie.GetMovies());
}
There's no need for a database, it's just used in tutorials because it's the most common case. But you can bind your views to any object you'd like.
You do not need that MovieDBContext class if you are not dealing with database. But having a model is a good idea to represent your entity(in this case the Folder). It is just a POCO class.
public class Folder
{
public string Name { set;get;}
public int NumberOfchilds { set;get;}
//Other properties as needed.
}
Now you can use the Model class to pass data between differnt places. For example. You can move the code which reads the data from file system to a Service class method and the method can return a list of this class/A single instance of this class as needed. Your controller action method can call the service method.
public class FolderService
{
public Folder GetRecentlyCreatedFolder()
{
var folder=new Folder();
//Set the properties of this object
// folder.Name="MySecret";
return folder;
}
}
and in your Action method
public ActionResult Items()
{
var srv=new FolderService();
var recentFolder=srv.GetRecentlyCreatedFolder();
return View(recentFolder);
}
Yes, you can use a model which is not stored in a database at all. Your case sounds like an obvious example.
Model, View, Controller makes database access easily abstractable but doesn't necessitate a database.
As much as I like entity framework I've never loved how most tutorials for MVC seem to marry the two - They are essentially unrelated and I think it really muddies the waters for a lot of programmers new to the framework.
All you need for a model is just a plain old class. Instead of using the dbcontext you'd simply use whatever code you need to load your data.

ActionResult parameters with no default constructor

Obviously there are a number of ways to do this, but I thought I'd ask for a little feedback on benefits and drawbacks of the approaches.
First of all, the NerdDinner tutorial's Edit Action is in the form (say Form A):
[HttpPost]
public ActionResult Edit(int id, FormCollection collection) {
It seems to me that if you shape your ViewModels well to match your views, that the approach Form B:
[HttpPost]
public ActionResult Edit(MyViewModel mvm) {
just seems like a better, cleaner approach. I then just map the VM properties to the Model properties and save. However, if this ViewModel has other entities embedded in it that are initialized via the constructor (for example in the nerddinner tutorial), then this edit action fails if there is no default constructor and you'd have to use the first approach.
So, the first question is do you agree that generally Form B is usually better? Are there drawbacks?
Secondly, it seems then if Form B is used, the decorator type validation would need to be in the ViewModel. Are there advantages of embedding entities in ViewModels and keeping the validation at the entity level only?
This is a pretty general SO question.
the first question is do you agree that generally Form B is usually better?
The only time I do not use Form B is when I upload files. Otherwise, I don't believe anyone should ever need to use Form A. The reason I think people use Form A is a lack of understanding of the abilities of ASP.Net's version of MVC.
Secondly, it seems then if Form B is used, the decorator type validation would need to be in the ViewModel.
Sort of / it Depends. I'll give you an example:
public IValidateUserName
{
[Required]
string UserName { get; set; }
}
public UserModel
{
string UserName { get; set; }
}
[MetadataType(typeof(IValidateUserName))]
public UserValiationModel : UserModel
{
}
The validation decorator is in an interface. I'm using the MetadataType on a derived class to validate the derived type. I personally like this practice because it allows reusable validation and the MetadataType/Validation is NOT part of the ASP.NET core functionality, so it can be used outside of ASP.Net (MVC) application.
Are there advantages of embedding entities in ViewModels ..
Yes, I do my absolute best to never pass a basic model to the view. This is an example of what I don't do:
public class person { public Color FavoriteColor { get; set; } }
ActionResult Details()
{
Person model = new Person();
return this.View(model);
}
What happens when you want to pass more data to your view (for partials or layout data)? That information is not Person relevant most of the time so adding it to the Person model makes no sense. Instead, my models typically look like:
public class DetailsPersonViewModel()
{
public Person Person { get; set; }
}
public ActionResult Details()
{
DetailsPersonViewModel model = new DetailsPersonViewModel();
model.Person = new Person();
return this.View(model);
}
Now I can add required data the DetailsPersonViewModel that view needs beyond what a Person knows. For example, lets say this is going to display a for with all the colors for the Person to pick a favorite. All the possible colors aren't part of a person and shouldn't be part of the person Model, so I'd add them to the DetailPersonViewModel.
public class DetailsPersonViewModel()
{
public Person Person { get; set; }
public IEnumerable<Color> Colors { get; set; }
}
.. and keeping the validation at the entity level only?
System.ComponentModel.DataAnnotations weren't designed to validate properties' properties, so doing something like:
public class DetailsPersonViewModel()
{
[Required(property="FavoriteColor")]
public Person Person { get; set; }
}
Doesn't exist and doesn't make sense. Why ViewModel shouldn't contain the validation for the entity that needs validation.
this edit action fails if there is no default constructor and you'd have to use the first approach.
Correct, but why would a ViewModel or a Entity in a ViewModel not have a parameterless constructor? Sounds like a bad design and even if there is some requirement for this, it's easily solved by ModelBinding. Here's an example:
// Lets say that this person class requires
// a Guid for a constructor for some reason
public class Person
{
public Person(Guid id){ }
public FirstName { get; set; }
}
public class PersonEditViewModel
{
public Person Person { get; set; }
}
public ActionResult Edit()
{
PersonEditViewModel model = new PersonEditViewModel();
model.Person = new Person(guidFromSomeWhere);
return this.View(PersonEditViewModel);
}
//View
#Html.EditFor(m => m.Person.FirstName)
//Generated Html
<input type="Text" name="Person.FirstName" />
Now we have a form that a user can enter a new first name. How do we get back the values in this constructor? Simple, the ModelBinder does NOT care what model it is binding to, it just binds HTTP values to matching class properties.
[MetadataType(typeof(IPersonValidation))]
public class UpdatePerson
{
public FirstName { get; set; }
}
public class PersonUpdateViewModel
{
public UpdatePerson Person { get; set; }
}
[HttpPost]
public ActionResult Edit(PersonUpdateViewModel model)
{
// the model contains a .Person with a .FirstName of the input Text box
// the ModelBinder is simply populating the parameter with the values
// pass via Query, Forms, etc
// Validate Model
// AutoMap it or or whatever
// return a view
}
I have not yet taken a look at the NerDinner project, however, I generally try to avoid having a ViewModel in the POST of an action and instead, only have the elements of the "form" submitted.
For instance, if the ViewModel has a Dictionary that is used in some kind of dropdown, the entire dropdown will not be submitted, only the selected value.
My general approach is:
[HttpGet]
public ActionResult Edit(int id)
{
var form = _service.GetForm(id);
var pageViewModel = BuildViewModel(form);
return View(pageViewModel);
}
[HttpPost]
public ActionResult Edit(int id, MyCustomForm form)
{
var isSuccess = _service.ProcessForm(id);
if(isSuccess){
//redirect
}
//There was an error. Show the form again, but preserve the input values
var pageViewModel = BuildViewModel(form);
return View(pageViewModel);
}
private MyViewModel BuildViewModel(MyCustomForm form)
{
var viewModel = new MyViewModel();
viewModel.Form = form;
viewModel.StateList = _service.GetStateList();
return viewModel;
}

Send a view model from ajax to controller

Is it possible to create an object in a view and send it to a controller through ajax?
using the
$.ajax({
type: "POST", etc....
???
I want to send an object of the type that I receive in the view as
#model Project1.ViewModels.ModelSample
It's possible
This is perfectly (and easily) possible.
What about complex objects?
#xixonia provided all the information you may need to do so. But those examples are rather basic and may not provide information in case you have some sort of complex objects as:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public Person Spouse { get; set; }
public IList<Person> Children { get; set; }
}
Any object that has more than a single level of properties in its tree is regarded as a complex object. Using technique provided by #xixonia will fail to work in this case.
So if you'd like to also use this kind of scenario I suggest you read this blog post that describes the whole problem in detail as well as provides a rather simple jQuery plugin that makes it possible to send even complex objects to Asp.net MVC controller actions that will be model bound to your whatever complex strong type.
Other posts on the same blog may also prove to be helpful:
successfully model bind forms to IList<T> action parameters (or within complex type parameters)
handling validation errors with Ajax requests
If you'll be using Ajax along Asp.net MVC you will find these posts very useful and will save you much of your development time when you run against such issues.
This is the way it worked for me:
$.post("/Controller/Action", $("#form").serialize(), function(json) {
// handle response
}, "json");
[HttpPost]
public ActionResult TV(MyModel id)
{
return Json(new { success = true });
}
Is it possible to create an object in
a view and send it to a controller
through ajax?
Absolutely. You can use ASP.NET MVC's model binding for this.
var data =
{
Id: 5,
Value: "Hello, world!"
};
$.post('Home/MyAction', data);
And you should have a matching POCO:
public class MyPoco
{
public int Id { get; set; }
public string Value { get; set; }
}
And an Action which takes your model to bind:
public ActionResult MyAction(MyPoco myPoco)
{
if(ModelState.IsValid)
{
// Do stuff
}
}
This should automatically deserialize your request into a POCO.

how to edit json data runtime?

i want to add the data to existing generated json data in my asp.net mvc application , what i have to do ?
means , suppose i have class Company that having list of Departments as property. but json serialization is not able to support such kind of circular reference. so i thought how if, i get serialize the Company object first without list of Departments, then get departments for each company and then serialize this list and append data to company serialized data. i know this may be wrong way . but i have to do because of time ultimatum. please guide.
You could define a view model where you won't have any circular references:
public class DepartmentViewModel
{
public string DepartmentName { get; set; }
}
public class CompanyViewModel
{
public IEnumerable<DepartmentViewModel> Departments { get; set; }
}
and then you would map between your model and view model (you could use AutoMapper for this) and finally return the view model to the view.
For example:
public ActionResult Index()
{
var companies = _repository.GetCompanies();
var companiesVM = Mapper.Map<IEnumerable<Company>, IEnumerable<CompanyViewModel>>(companies);
return Json(companiesVM, JsonRequestBehavior.AllowGet);
}
Now you no longer would have circular references and you will be able to successfully serialize the view model to JSON and you would only pass the information that is required to the view.

Resources