How should I serialize dynamic form elements in MVC 5? - c#

I have an MVC 5 project and part of that is a registration. Presently the form submits using the standard form submit action and my model binder does its job gloriously and all is good.
However, I now need to add a dynamic element to my form such that a user needs to be able to add on the fly invitations to add team members via a textbox for an email address and a dropdown list for that team members role... and an add another button to add another textbox and dropdown list for the next team member... and the next... ad infinitum...
Upon form submission, my model binder is going to fall over and not know what to do with these dynamic elements, so I need suggestions for how to get my model binder to deserialize these items into an array of email & role (role binds to an enum).
I've had it suggested that client side script can catch the submission and serialize the items to a text string and put that in a hidden form field that I can then deserialize manually on my controller action, which seems like it'll work okay, but it feels dirty.
What is the most straightforward way of achieving this? Is there anything built into .NET that will automatically handle this somehow if I configure my view correctly?

Your model can store your "dynamic" fields in a collection like:
public List<string> Emails { get; set; }
In your view you just create subsequent indexed names (exact naming depends on how you're generating this new fields):
model.Emails[0] // name="Emails[0]"
model.Emails[1] // name="Emails[1]"
In your controller action, there should be nothing special the model binder has to do. It will easily be able to handle the collections.

There is an old article from Phil Haack about binding to a List:
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/
I guess you could add a ICollection<Invitation>-Property to your model and set the Name of the form fields as explained in the article.
Although personally I would bind the data to a JavaScript-ViewModel and post JSON back to the Server using Ajax.

Upon clicking the "Add more" button, simply inject the textbox and dropdown and let the form serialize like usual.
On the server, accept a list of invitations:
public class Invitation
{
public string EmailAddresss {get; set;}
public int InvitationType {get; set; }
}
public ActionResult Register(MyCurrentModel dto, Invitation[] invitations)
{
//..
}

Related

MVC form view for eav database

I want to write a form to submit data about people that could have a greatly varying amount of fields, it is getting this data from an eav database. My idea was to write a model with a Dictionary of parameters. Something like
public class MyModel
{
public Dictionary<string,string> Parameters {get;set;}
}
Where the key would be the parameter name and the value would be the value. Then in the view I would just create a Html.TextBoxFor(...) each parameter in the dictionary and submit the form. The model would also handle stuff like populating the dictionary etc.
Another intern told me I should just use json and ajax/angularjs. The form isn't smart at all, just a big list of fields you have to fill in then submit.
Is there a downside to doing it just in razor and server code in this case?
If you are just editing preexisting data, you don't have to add any new data, then doing it with pure razor should be just fine, check this question, I think it will help you. However if you have dynamically add or delete, some pairs then this approach will not be enough and you should consider listening to the other intern.

What approach should be used for model binding to an exisiting session object?

Here's my problem:
We have an intranet asp.net mvc 3 application with a controlled set of users. We have a Person class, that contains a large amount of information, that is initially loaded and stored in the session. The data/editing for this object spans across many screens. Basically, each screen is a subset of the Person's data.
I'm trying to take advantage of the built in model binding in asp.net mvc. Should I create a data class that binds the form data from each screen and then updates my session object using a service object?
Example below: DxFormData contains a subset of the person data and will only be used as a parameter on this method.
public ActionResult Dx(DxFormData data)
{
// Update current session Person object with data passed in if modelstate is valid
var viewModel = this.GetDxViewModel();
return View(viewModel);
}
public class DxForm Data
{
public string AdmitDx { get; set; }
public string PrinDx { get; set; }
}
I'm looking for thoughts on this approach and if there's a better solution available to me. The problem that I see, is that the person class contains all the data and I'm creating another class with a subset of that data. Obviously, duplicating the properties.
Side note: I did write a custom model binder that returned the session person for binding. However, I am continually getting errors when it attempts to bind.
I don't see problem with this approach. If you try to use the Parent class as the action parameter then in each form submit action then you will get validation errors because the model is not completely filled, so you should use view models in this case and unfortunately you can't avoid duplicating properties.

MVC3: Binding models to dynamically created html elements

I have a model which contains lists of other models, which also contains lists of other model types like the following for example:
public class Report
{
public string ReportId {get; set;}
public List<ReportOutput> ReportOutputs;
}
//output types = PDf, csv, txt, etc.
public class ReportOutput
{
public int OutputType {get; set;}
public List<DeliveryMethod> DeliveryMethods;
}
//delivery methods = email, ftp, etc.
public class DeliveryMethod
{
public string MethodName {get; set;}
}
I have a view that dynamically creates elements based on the contents of these objects using jQuery. The view allows users to check checkboxes to add or remove different outputs and within each output, different delivery methods. I need to know how to get the information back to the controller to load into a model to send back to the database. From reading around, it seems that I would just need to instantiate a model in the controller, then give each element in the view a name which corresponds to the model's properties and than call the controller function to retrieve all the data and continue the saving with the newly filled model, but my attempts at creating this controller function have failed.
So my question is, how would I create the controller function and do I just need to use the corresponding names on the html elements to allow a model to be created based on the information on the view?
If you follow the below pattern in generating name of form fields, the default model binder will take care of the rest else you have to do the model binding process yourself (tough job!).
ReportId,
ReportOutputs[0].OutputType,
ReportOutputs[0].DeliveryMethods[0].MethodName,
ReportOutputs[0].DeliveryMethods[1].MethodName,
ReportOutputs[1].OutputType,
ReportOutputs[1].DeliveryMethods[0].MethodName,
You should checkout the following article which covers those subjects and explains the naming conventions of your input fields that the default model binder expects so that it can bind them back when the form is submitted.

Beginner mvc where to call methods

I am doing big project in Web Forms and entered a big mess of code(can be solved with little refactoring), so I decided to take a peek at mvc, seems like everyone favores it over web forms.
I have dll file with all LINQ to SQL classes and methods for existing sql db and I started teaching myself by reacreating this project in mvc.I first recreated my homepage from webforms to razor, so far so good and I recreated one of the user controls to partial view and looped it.
Partial view is strongly typed with one of L2S class, the thing is there is some raw data in it.Like for example My model for partial view is my L2S class PostDetails: it consist od some data ready from output like: Title, Permalink, ViewsNumber etc. but it also cointains some raw data like UserId(I need to call method from dll to get username),DateTimeCreated(on which I also need to call method to get time difference), In webforms I would do this in codebehind but I'm not sure where to do it in mvc, maybe in controller and pass it in ViewData.I am also asking this for future, not just this case.
You should perform those actions in the controller. The controller is exactly what it sounds like, it controls the data flow between the model and the view.
Here is an example using your PostDetails:
PostDetailsModel
String Title {get;set;}
String Permalink {get;set;}
Int ViewNumber {get;set}
Int UserId {get;set}
DateTime DateTimeCreated {get;set;}
GetDetailsView: this will be requested by your user, and will be a visual representation of the PostDetailsModel (however you want to format that). When this View is requested, a call is made to your controller....
PostDetailsController
//This method will (by default) come from calling [BASEURL]/PostDetails/GetDetails
public ActionResult GetDetails()
{
var details = new PostDetailsModel();
details.UserId = GetUserId();
details.ViewNumber = GetViewNumber();
....
//By default this looks for a view in the PostDetails folder
//by the name of your method (GetDetails)
return View(details);
}
Notice how the controller is the router between the model and the view, basically. A note, however, it would be better to fill your model from methods contained within some sort of business layer (however you implement that). Something like var details = BL.GetDetails();
Also, when the user makes requests to save data, then you can do that with another method that takes the data (whether it be the PostDetailsModel or an int or...) and does whatever it needs to do, then it can redirect back to the display action (or wherever you need it to go)
There is a wealth of information on MVC with a simple google search. Here is Microsoft's overview, but the wikipedia article is very succinct if you just want the basics
In MVC, All your requests will be handled by an action method in a controller. and then controller returns a view. So you can get the data in your controller (or a different layer which will be called from the controller) and pass that data to your view.
Strongly typed views are a clean way of doing things. Create a ViewModel for your scenario. Mostly ViewModels looks similar to the Entities. Ex : For Displaying the details about a customer, i will create a viewModel called "CustomerViewModel"
public class CustomerViewModel
{
public string CustomerId { set;get;}
public string FirstName { set;get;}
}
Then in my CustomerController, I will have a get method for the customer
public class CustomersController : Controller
{
public ActionResult Details(int id)
{
CustomerViewModel objCustomer=new CustomerViewModel;
objCustomer.FirstName="Samuel";
//Instead of hardcoding the values here , you can get it
// from the database using the id and assign to the properties
return View(objCustomer);
}
}
And you will have a view called "Details.chtml" in your Views\Customer
folder which is strongly typed to your CustomerViewModel
#model CustomerViewModel
<div>
<h2>#Model.FirstName</h2>
<p>#Model.CustomerId</h2>
</div>
This can be accessed like http://yourdomain.com/Customer/Details/25
Personally i prefer to keep my controller actions thin. so i write the GetFromDatabase code in a seperate service layer and i just call that method from my action method
I think that you'll find this article very useful:
MVC Overview
It explains in detail, as to what each component should be used for:
Models. Model objects are the parts of the application that implement
the logic for the application s data domain. Often, model objects
retrieve and store model state in a database. For example, a Product
object might retrieve information from a database, operate on it, and
then write updated information back to a Products table in SQL Server.
Views. Views are the components that display the application s user
interface (UI). Typically, this UI is created from the model data. An
example would be an edit view of a Products table that displays text
boxes, drop-down lists, and check boxes based on the current state of
a Products object.
Controllers. Controllers are the components that handle user
interaction, work with the model, and ultimately select a view to
render that displays UI. In an MVC application, the view only displays
information; the controller handles and responds to user input and
interaction. For example, the controller handles query-string values,
and passes these values to the model, which in turn queries the
database by using the values.

Dynamic List in Model for MVC3 Form

I'm building a driver's application for employment and I'd like the list of 'accidents' to be dynamic in the sense of only one field appears, but they can add however many they need and once added they appear in a table above the input..
I'm trying to find out what the best way to do this is in a MVC3 Form that is using Razor syntax?
Model has a declaration similar to...
public class FormModel {
...other properties
public IEnumerable<AccidentDetail> AccidentDetails { get; set; }
...other properties
}
This is very much shortened, but wanted to ensure that I was declaring it properly in the model and then I need to know how it's generally handled in the Form to do something like this. I can't make any assumptions to the existence of an accident or the limit of how many they may have.
I personally would approach this with some JavaScript. In particular, I'd use jQuery to add a new field to the table when a button is clicked to "Add another accident". You can use jQuery to grab the values of the fields into an array. The array of accidents would be serialized to json and stored in a hidden field on the form that would be submitted to the server. In your controller you could deserialize that string of json to your strong type. On the server side I've used Json.NET with great success. On the client side you can use Doug Crockford's json2.js. Feel free to email me if you need a little bigger push in the right direction.

Categories