ASP.NET MVC bind array in model - asp.net-mvc

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.

Related

combine 2 related model in mvc

I have 2 models like this.
public partial class Question
{
public int QuestionId { get; set; }
public string QuestionText { get; set; }
public string Ans1 { get; set; }
public string Ans2 { get; set; }
public string Ans3 { get; set; }
public string Ans4 { get; set; }
}
public partial class UserAnswer
{
public int UserAnsId { get; set; }
public Nullable<int> QuestionId { get; set; }
public Nullable<int> UserId { get; set; }
public Nullable<int> AnsVal { get; set; }
}
As you can see QuestionId is in both the models. How can I render it in view. There are multiple questions. Question Moldel has data in initial run but UserAnswer doesn't.
How can I combine these 2 models so that I can use it as IEnumerable in view. Ans1,Ans2,Ans3,Ans4 has text and AnsVal in UserAnswer will get its value from Raiobutton.
make a combine class like below..i am not sure this is perfect or not..any suggestions are acceptable.
public class QuestionAnswerViewModel
{
public Question Question {get;set;}
public ICollection<UserAnswer> Answers {get;set;}
}
You want to create a ViewModel that represents the combined model objects. This keeps things clean, your model is just that, the model, what gets passed to the view can be the model but in many cases the concept of a ViewModel will make things easier to design while keeping your code loosely coupled and clean. This also keeps things that are not important to the View out of the equation aka particular properties in your model such as maybe a CreatedDate should not be passed to the View, especially since View requests will pass back the value as null since it is not being used in the view and thus not populated on postback. This could lead to you updating the database with a null value for CreatedDate simply because it was not used in the View.
Maybe you have a Model class library in your solution? If you do, create another class library called MyNamespace.Web.ViewModels or something like that. Also you should look into using a tool like AutoMapper that will populate the ViewModel on View request to the Controller and populate the model on View postback to the controller.

XtraGrid binding over complex and nested objects model

I'm wondering how to solve/simplify a task that sometimes pop-ups during developement with DevExpress XtraGrid suite.
Sometimes i fall into this case:
Given these 2 classes that represents the model classes that comes from the Business Logic layer:
public class Customer
{
public Int32 CustomerId { get; set; }
public String Name { get; set; }
public String Address { get; set; }
public List<Order> Orders { get; set; }
}
public class Order
{
public Int32 OrderId { get; set; }
public String ItemCode { get; set; }
public Int32 Quantity { get; set; }
public Decimal Price { get; set; }
public DateTime Date { get; set; }
}
I'd like to create a simple window that shows an XtraGrid that allows edit/add/remove a list of customers and its nested orders.
In order to do that, i've created a simple form with a GridControl and a GridView controls with the AllowAddRow and AllowDeleteRow properties == true.
Then, in Form1 class i've done the following:
//List of my customers
private List<Customer> _customers;
public Form1()
{
//Initialize UI components
InitializeComponent();
//Call the provider in order to get customers
CustomerProvider cp = new CustomerProvider();
_customers = cp.GetCustomers();
//Initialize bindingSource
BindingSource bs = new BindingSource();
bs.DataSource = _customers;
//Set GridControl's dataSource
gridControl1.DataSource = bs;
}
Now i've got beautiful GridControl that shows the content of my List.
But now here's the problem...how can i add or delete row?
Infact:
If i set the focus on a row and i press "Delete" key, it doesn't
work.
If i try to add a new row, when it looses focus, it suddently disappears.
Obviously i'm missing something. Unfortunately i found the DevExpress documentation a quite confusional (in my opinion) about this kind of argument and the best practises, so i can't reach my goal.
Someone can help me?
PS.
This is the hyperlink for the .csproj of my sample.
Set the gridControl1.UseEmbeddedNavigator property to true. You'll get a data navigator widget at the bottom of your view.
That only gets you halfway there, however. If you want to be able to add Orders to a Customer from the grid, your Customer class needs to use BindingList instead of List for the Orders property.
See here for more information. If you find the documentation lacking, you can also find helpful resources at the Support Center.
EDIT: Some other options to consider are:
Bind your grid to a database.
Bind to XML data and use a DataSet.
If you're already storing your data in a database, then option 1 would be the way to go. If you're not persisting your data anywhere yet, you could go either way.

Retrieving related data using linq

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]
}

Filter some property value in post data by ASP.NET MVC 3

I have a model like the followings:
public class MyModel {
[Required]
public string Name { get; set; }
public string Family { get; set; }
[Required]
public int Number { get; set; }
}
So for example in Edit View I have 3 Editorfor() objects and I am interesting to filter the post data of this page, actually I want to ignore Number field and just want to post Name and Family Also I need the validations of Number be active, One way is I remove Number property from MyModel and define in view by hand and write all validation script by own, but I am interesting to know is there any simpler way in MVC. Does anyone have any idea?
Controlling all that validation and model binding manually is way too complicated and error-prone. You should be using ViewModels
public class SomeSpecificViewModel
{
[Required]
public string Name { get; set; }
public string Family { get; set; }
}
public ActionResult SomeSpecificAction(SomeSpecificViewModel model)
{
//...
}
Now MVC wil validate only Name and Family
Any value not filled in the view will not be posted to the controller. However, if a field which is [Required] is not filled, then ViewModel.isValid will be false.

How should i design my ViewModel and save it using AutoMapper and EF?

Im not quite sure how to use ViewModels so i need some help on the following issue:
I am creating a online survey.
A user is able to create a multiple choice question. The domain entities that i use for this to happen are the following:
[Question]
int category_id { get; set; } // The category the question belongs to
int type_code { get; set; } // The type of question (I.E Multiple Choice)
string question_wording { get; set; } // The question itself
bool visible { get; set; } // Visiblity
int question_number { get; set; } // The number of the question
string help_text { get; set; } // Help text if the user doesnt understand the question
[Multiple_Choice_Question]
int choice_number { get; set; } // The order in which the MCQ answer possibility is shown
int choice_wording { get; set; } // The MCQ answer possibility
string help_text { get; set; } // help_text if the user doesnt understand the answer possibility
// This is a cross-reference table in my database that maps questions with choice possibilities
[Ref_Multiple_ChoiceAnswer]
int question_id { get; set; }
int mcq_id { get; set; }
In my View i need to be able to create the question and the choice possibilities (Multiple_Choice_Question) at the same time. The user writes the choice possibilties in a textbox, each seperated by a new line.
like
Cat
Dog
Mouse
Now that im working with two entities should i just put all the necessary properties in my ViewModel? Each Answer possibility is a new row in my database, and in the View it gets sent back as a string (the text in the textbox) - how do i solve this?
How do i use AutoMapper on [HttpPost] to bind the properties from the Question with a new Question Object and the answer possibilities with a Multiple_Choice_Question Object. Also, what is the best way to map theese two new entities in the Ref_Multiple_ChoiceAnswer table?
Thanks in advance
You are not supposed to bind props from view model. It`s so by design.
This drives design more towards oop.
State of Your model should be changed through invoked behavior.
E.g. instead of:
question.visible=questionViewModel.visible;
You should be using:
class QuestionController{
ActionResult Hide(int question){
var q=find(question);
q.Hide();
return q.As<QuestionViewModel>();
}
}
class Question{
void Hide(){
Visible=false;
}
}
That is why "binding properties" kind a makes no sense.

Resources