ASP.NET MVC data-attribute with auto-bind - asp.net-mvc

This is the sample ViewModel I get to the view:
public class CollectionOfStuffVM
{
public string Element { get; set; }
public bool IsPicked { get; set; }
}
This is asking for a Checkbox for multiple items, or a dropdown list if it is a single pick only.
But, what if I am drawing this in a custom way?
Eg. below (inside a editor template):
#Model.Element
All the "data-picked" stuff is being handled by javascript when something is clicked.
So, how would it be possible to automatically bind these custom "controls"?
I guess there's some work that needs to be done, i'm just not sure, where. Do I need to create a custom Input?
I know this auto bind would be doable with inputs, but i'm kinda avoding having to have hidden inputs being updated by Javascript.
Keep in mind this is just a simple example, the ViewModel is a bit more complex and it would be frustrating to have to build everything in Javascript to do an Ajax POST.

There's no such thing as two-way databinding when it comes to MVC. This is because, unlike something like a WPF application where everything runs on the same machine, a web application is disjointed, with server-side and client-side components.
If you want the data set by the client to be set back on the server, you have to post it to the server. If you handle that with a standard form, you must include some kind of input that has that value. If you do it with AJAX, you have a bit more freedom, as you don't need a physical HTML input element to hold the value, but you're still responsible for ensuring that the value makes it into the object you send to the server via AJAX.

Related

ASP.NET MVC: Is "views must be dumb" correct statement?

Most of the good references for MVC on web strongly suggest "views must be dumb". It should not contain any logic. This does not seems valid when I try to implement it.
Some of my views display only first name of student and some of them display only last name and some of them display full name. My database (and POCO and DTO) store name in separate components. I see best place to format the name is view.
My view changes on some actions on client side without hitting server. Example, on clicking some button, it hides some part of view and shows other and disable some controls. Or another button opens new window and takes some inputs and validates it. This input is never sent to server; it is only useful for some client side activities.
I have validations on server side. But just to save the hit to server, I also validate on client side.
Data binding with KnockoutJS.
Based on data (start and end date) received from server, I generate table on client side to display sections of that period slicing 1 hour each. This is something scheduling like GUI. I need to do date and time calculations in view to achieve this. When I was in stone age (ASP.NET WebForms), I was generating this table on server side; I know you are shocked. I shifted it to JS for performance.
In SPA, view hold most of the logic by fetching only necessary data from server through AJAX.
I can put many other similar examples here those force me to put some logic in view. Considering that view still holds logic and use of JS is increasing day by day, can we still say "views must be dumb" is a correct statement?
Some details explaining the same with respect to points above will help.
Notes:
Though my question is based on ASP.NET, I am expecting answers referencing to ONLY MVC as a design pattern; no matter what technology I use. So please do not suggest what is another way to do validations. Points above are just to note some of the cases where logic is necessary in view.
There might be something wrong in how I am implementing above points. But My only point is that, use of JS (and putting logic in views as a result) is increasing.
Everyone is welcome to contradict above points in case I am implementing it wrong way; just do not redirect entire discussion that way.
Edit 1:
#kayess: Yes, I have Models as well as ViewModels and this is obvious in MVC. Server logic that is strongly related to specific view and cannot be reused is put in ViewModels. Major part of domain logic which is reusable is put in Models. Even after having ViewModels, there are many things those I will prefer to do on client side. About narrowing the question, the basic answer to this question will be "Yes" or "No". Other details will be just to support the answer. I do not think this will attract opinions as there must be something about MVC views that I have not fully understood. The one answering the question just need to point that out to me.
I think generally by "views must be dumb" means specifically the server side part of the views. Having TypeScript/JS in a view is perfectly normal. I wouldn't however expect to have dozens of lines of C# in the view that is fetching records from a database.
However, having some very simple logic such as the following is pretty common:
#{
if(user.IsLoggedIn)
{
<span>You have new messages!</span>
}
else
{
<span>You need to login to view messages.</span>
}
}
However server side view code shouldn't get much more complicated than that because that breaks down the whole point of separation concerns and having appropriate abstractions and design patterns etc, and just becomes unmaintainable.
See also: Microsoft documentation on "Adding a View"
May it be any technology there are set of theories supporting different concepts, like you said view should be dumb there are advocates of model should be dumb.
Idea here is let your view model take care of the manipulation if any needed, and let your view refer to view model. So that change is centric.
And I believe you are alredy doing that.
Although this is an old question and has an accepted answer, I want to add some points not covered in any answers.
I think you are overlooking cases where more logic can be pushed to your domain model. For example, you mention the concept of "Name" and that you must use conditional logic in your views to decide whether to show first, last or full name. I have a class called Name in my domain model. It incorporates the logic of FirstName, LastName and FullName like so:
public class Name
{
public Name(string firstName, string lastName)
{
this.FirstName = firstName;
this.LastName = lastName;
}
public string FirstName { get; }
public string LastName { get; }
public string FullName
{
get { return $"{this.FirstName} {this.LastName}"; }
}
}
In my UI I have have ViewModels with the whatever name property I need. When I convert my domain models to view models my conversion logic tells the ViewModel which property to use. If I need FullName I use Name.FullName. If I just need FirstName, I use Name.Firstname. At no point do I need to put conditional logic about names in my views.
In addition, you can use custom helpers, formatters and extensions to encapsulate reusable logic for views. For example, I have utilities to format phone numbers, addresses etc, so that I do not have to put this logic in every view that needs it. I also have a paging module in my UI that encapsulates paging so that I do not have to have paging logic in my views other than to call the pager.
Partial views are also helpful. For example, from the accepted answer, I would put the following in a partial view and just call it in each view, rather than repeating the conditional logic it in every view:
#{
if(user.IsLoggedIn)
{
<span>You have new messages!</span>
}
else
{
<span>You need to login to view messages.</span>
}
}
My point is there is a lot you can do to move logic out of views to keep them dumb.

Make asp.net mvc validation work without helpers

Could someone provide a good tutorial on how may I validate my html fields with unobtrusive,
but without using MVC helpers.
Is it possible at all?
I would like to keep the plain html and use input type="text" field instead of mvc helpers <%= Html.TextBox("Name") %> but still using the model validation..
public class Employee
{
[Required]
public string Name { get; set; }
}
Also is it possible with jquery Ajax?
Thanks
While it is possible to perform unobtrusive validation in MVC without using helpers, it will be painfully for you as developer to do it manually without usage of mvc helpers. Saying strictly, it will kill your performance and make your code unreadable.
Basically, unobtrusive validation consists of two parts: server side, via data-attributes to your model fields and MVC Helpers, which generate necessary markup, and client side library, jquery.validate.unobtrusive.js, which parses those markup to meaningful parts for jquery validate plugin.
So, in general, you can manually write necessary markup, as long as validation js library will be loaded, validation will work. For example, field, which is subject of validation, must be marked with data-val='true' attribute. If you want to make your field required, you should write additionally something like data-val-required="error message". For length validation - data-val-length-min="5" (obviously, minimum) data-val-length-max="50" (maximum length), data-val-length="Min 5 max 50 chars required".
While, when using normal mvc approach, it is just a question of model attribute:
[Required]
[StringLength(50, MinimumLength = 5)]
public string Name { get; set; }
and one line of code in markup:
#Html.TextBoxFor(o=>o.Name)
Nice, shiny, separates View and Model, and helps KISS.
And for second part of your question. If I understood your problem correctly, you want to validate dynamic forms. Probably it will be answer:
jquery.validate.unobtrusive not working with dynamic injected elements

Knockout + mvc 3 + Validation

In the controller I would like to be able to get to the client validation rules of the model. I've attached some attributes using data annotations and would like to be able to pass something back to the client via the ajax call so I can then build the jquery validate options automatically.
Normally this is done for free with the unobtrusive stuff, but I'm trying to leverage knockout binding, while still not having to replicate the validation rules on both the server and client.
Without using reflection on the model server side I'm a little unsure on how to achieve this.
In my Mvc Controls Toolkit I developed Helpers based on the knockout library. These helpers not only help in writing the knockout code, but enhance the knockout library with Unobtrusive validation and globalization. Moreover, the binding mechanism is enhanced to include complex controls such as a DatetimePicker, and other "complex" (made by different html parts) controls.
Finally, knockout templates can be defined through Razor helpers.
See the documentation here, here, here and here. I also have some tutorials that show how to implement advanced features with my helpers:
Low BandWidth Transfers with The Client Side Templates of the Mvc Controls Toolkit
Handling Big Amounts of Data with Client-Side Templates
Handling Big Amounts of Data with Client-Side Templates 2
Depeneding on what you exactly need to do, Breeze js can be the best solution. particularly, if you're using EF, you can replicate most of the functionality of the server EF's DbContext on the client side, including, of course, the validation, but also change tracking, .saveChanges, a simple syntax that resembles LINQ queries, caching, serializing and deserializing to allow working offline, and many other things.
The basic steps to work with Breeze js are:
create an EF model in the server
add a NuGet Package on the server to create Web API Services that expose the model to the client side. This is done with a surpringly low number of C# code. One of the things that this does is exposing the metadata: definition of objects, relations, and extra information, like data annotations validation info
add a js Nuget Package for the client side which will be used to replicate the EF behavior on the client side.
Of course, not all of the functionality on the server will be replicated on the client, but you can do a lot of things:
create new entities on the client side
make queries on the client side, which will be executed on the server and returned to the client
modify entities on the client: create, modify, delete...
create relations on the client side: for example create new chlid entities in a parent object
call saveChanges on the client side, which will transfer all the tracked changes to the server so that the backend is updated
of course, while you do this, you'll get automatic client validation, and also additional server validation whenever you call .saveChanges
Finally, you can extend and modify the server code to include some business logic, so that you can do much more than simply exposing the EF model to the client.
That's quite a task. You want to be able to convert your C# code into Javascript with respective data type conversions etc. You'll be better off writing down two separate sets of validation at server and client side both. It would be a lot more easier to maintain that than to write your own conversion framework all by yourself and maintaining it
On the model use attributes validation that you like:
public class ModelWithValidation
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
In mvc forms
#using( Html.BeginForm())
{
#Html.TextBoxFor(m => m.Name, new {data_bind = "value: name"})
#Html.ValidationMessageFor(m => m.Name)
}
In jQuery test if form is valid onSubmit or in knockout save function call the next code to validate input. You must include jQuery.unobtrusive* and jQuery.validate* libraries. Don't forget to validate input on server side also!
var form = $("form");
form.removeData('validator');
form.removeData('unobtrusiveValidation');
$.validator.unobtrusive.parse(form);
$("form").valid() //true false

ASP.NET MVC: Best practices for keeping session state in a wizard-like app

Let's say I have a Web application implemented like a set of wizard pages to edit a complex object. Until the user clicks on the "Finish" button, the object doesn't get saved to the back-end system (a requirement), so in the meantime I have to keep the whole information about the object in some kind of a session state.
Also, some of the wizard pages have to show combo and list boxes with potentially large number of items. These items are fetched from the back-end system using a Web service.
Coincidentally, the wizard allows the user to freely jump from one wizard page to any other (using tab links on top of the form), so it's not a simple "next, next... finish" thing.
Additional constraint: the Web application runs on a Web farm and the customer is weary of using server-side session state. In the best case they want to keep the size of the session state minimal (they had problems with this in the past).
So basically there are two problems here:
How/where to keep data entered by the user in the Wizard?
Whether to cache the combo/list items received from the back-end and if so, where?
Options I'm considering:
Storing the object in a WebForms-like ViewState (by serializing it into the HTML page). This would also include the combo box items. Obviously, there could be a problem with HTML pages becoming very large and thus Web application will be slow.
Storing it into server-side session state, regardless of the customer's wishes and without knowing how the performance will be affected until it is tested on the actual Web farm (late in the project).
I cannot decide between the two. Or is there another alternative?
Why cache at all? You could just have the tabbed pages where each page is a div or panel and just display the current div relating to your tab. That way you dont have to keep track and process all the inputs when the user submits the form.
Is it possible to store the wizard data in a temporary table in the database? When the user finishes the wizard the data is copied from the temporary table and deleted. The temporary table includes a timestamp to remove any old uncompleted data.
As Daisy said, it doesn't have to be cached. You could also use hidden form fields. Because these could map to the same object on each controller action, you could progressively build the object through successive pages.
//Here's a class we're going to use
public class Person
{
public int Age {get;set;}
public string Name {get;set;}
public Person()
{
}
}
//Here's the controller
public Controller PersonCreator
{
public ActionResult CreatePerson()
{
//Posting from this page will go to SetPersonAge, as the name will be set in here.
return View();
}
public ActionResult SetPersonAge(Person person)
{
//This should now have the name and age of the person
return View(person);
}
}
//Here is your SetPersonAge, which contains the name in the model already:
<%= Html.Hidden("Name", Model.Name) %>
<%Html.TextBox("Age") %>
And that's pretty much it.
I can suggest a few more options
Having the entire wizard as a single page with the tabs showing and hiding content via javascript on the client-side. This may cause the the initial page to load slower though.
Caching the data at the server using the caching application block (or something similar). This will allow all the users to share a single instance of this data instead of duplicating across all sessions. Now that the data is lighter, you may be able to convince the customer to permit storing in the session.
There is a lot of resistance in the MVC community against using Sessions. Problems are that a lot of us developers are building login systems like a bank website. One could argue for hidden fields and that works for some situations but when we need to time a user out for security and compliance, then you have several options. Cookies are not reliable. Relying on Javascript timers are not reliable and are not 508 compliant as the goal should be to degrade gracefully. Thus for a Login, a Session is a good option. If you write the time to the client browser, to the server database or server file system, you still have to manage the time per user.
Thus use Sessions sparingly, but don't fear them. For the wizards, you technically can serialize hidden fields passing them around. I suspect the need and scope will become much greater and an authorization/authentication implementation with Sessions will be the crux of the application.
If you cannot use ajax (for validation & dropdowns and ability to convert wizard to tabbed page) and cannot use html5 (for dropdown caching and form state saving in local storage), then I think you are pretty out of available "best practices" and you have to resort to bad (or worse) one.
As MVC is opponent of WebForms regarding session usage, maybe you can use a workaround? For example, besides storing all these values in some temporary database records you need to clean up later, you could set up AppFabric extension for Windows Server and use it to store dropdown list items (and scope can be for all users, so if more users are using system at the same time you need only one call to web service to refresh cache), and also to temporary store your objects between steps. You can set your temporary objects in AppFabric to automatically expire so cleanup is not necessary. It can also be of help for speeding up other parts of your system if you extensively call another system over web services.
I've been dealing with the same issue and, while my requirements are a little simpler (keeping state for just a few strings), my solution may work for you. I'd also be interested in hearing others thoughts on this approach.
What I ended up doing is: in the controller I just dump the data I want into the Session property of the Controller and then pull it out next time I need it. Something like this for your situation:
//Here's the controller
public Controller PersonCreator
{
public ActionResult CreatePerson()
{
//get the age out of the session
int age = (int)(Session["age"]);
//do something with it...
return View();
}
public ActionResult SetPersonAge(Person person)
{
//put the age in the session
Session.Add("age", person.Age);
return View(person);
}
}
The thing I like about this is I don't have to put a bunch of hidden params around on my view pages.
The answer to this can be found in Steve Sanderson's ASP.NET MVC 2/3, and requires a reference to the MVC Futures assembly. This link to Google Books is exactly what he does.
In essence, you serialize the wizard data to the View. A hidden field is rendered storing all of the acquired information.
Your controller can work out what to do through the use of the OnActionExecuting and OnResultExecuted (to cater for redirects) to pass it to the next view.
Have a read - he explains it much more thoroughly than I can.

Dynamic (Runtime Generated) Forms in ASP.NET MVC [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
This is a general design question: How would you implement a dynamic (runtime generated) form in ASP.NET MVC?
Here's the situation:
A site admin can define form parameters (fields, type of fields, validation) with a GUI (MVC view).
As needed, the runtime generates the form for the end user based on the admin configuration. I'm assuming that all of this logic would reside in the controller - or perhaps extension methods, action filters or something like that.
End user fills out the form, hits submit, information is captured in database.
The customization does not need to support nested controls, 3rd party controls and so forth, but I suspect a very elegant design would allow for that. Mostly, I just need the admin to be able to specify additional fields as textboxes, checkboxes, radio buttons and comboboxes. I will also need the application to allocate a space for this data to be saved in the db, but I believe I have that part figured out.
Thanks for the help.
I had the same need in a recent project. I created a class library for this. I just released a new version of the library.
Maybe it can help you:
ASP.NET MVC Dynamic Forms
You can do this very easily using my FormFactory library.
By default it reflects against a view model to produce a PropertyVm[] array, but you can also create the properties programatically, so you could load settings from a database then create PropertyVm.
This is a snippet from a Linqpad script.
```
//import-package FormFactory
//import-package FormFactory.RazorGenerator
void Main()
{
var properties = new[]{
new PropertyVm(typeof(string), "username"){
DisplayName = "Username",
NotOptional = true,
},
new PropertyVm(typeof(string), "password"){
DisplayName = "Password",
NotOptional = true,
GetCustomAttributes = () => new object[]{ new DataTypeAttribute(DataType.Password) }
}
};
var html = FormFactory.RazorEngine.PropertyRenderExtension.Render(properties, new FormFactory.RazorEngine.RazorTemplateHtmlHelper());
Util.RawHtml(html.ToEncodedString()).Dump(); //Renders html for a username and password field.
}
```
Theres a demo site with examples of the various features you can set up (e.g. nested collections, autocomplete, datepickers etc.)
Another option is to have a very loosely coupled database schema.
//this will contain all the fields and types that the admin user sets
**ApplicationFields**
FieldName
FieldType
...
//these are all the values that have some mapping to a ParentObjectID
**FormValues**
ParentObjectID
FieldName
FieldValue
When you submit your runtime generated View (from ApplicationFields) then just loop through your FormCollection and try and set it on the ParentObject you need to update.
public ActionResult MyForm(FormCollection form)
{
//this is the main object that contains all the fields
var parentObject;
foreach (string key in form)
{
parentObject.SetValue(key, form[key]);
}
...
Then your parentObject might be something like this...
public partial class ParentObject
{
IList _FormValues;
public void SetValue(string key, string value)
{
//try and find if this value already exists
FormValue v = _FormValues.SingleOrDefault(k => k.Key == key);
//if it does just set it
if (v != null)
{
v.Value = value;
return;
}
//else this might be a new form field added and therefore create a new value
v = new FormValue
{
ParentObjectID = this.ID,
Key = key,
Value = value
};
_FormValues.Add(v);
}
}
One way to do this is to create your own ModelBinder which would be at the heart of your generated forms. A modelbinder is responsible for validating the ModelState and rebuilding the typed ViewDataModel (assuming your views are typed).
The DataAnnotations model binder could be a good reference for this what this custom modelbinder allows you to do is via Attributes on your ViewDataModel describe the attribute's validation (and hint at UI rendering). However this is all defined compile time but would be a great reference to start off writing a custom modelbinder.
In your case your model binder should get the validation for a field at runtime from an xml file/string.
If you have a route like:
routes.MapRoute(null, "Forms/{formName}/", new { action = "Index", controller = "Forms", formName = ""}),
Then you could locate the correct form xml in FormsController.Index(string formName) and pass it to the view.
The FormsModel should hold all the possible methods to get data I dont see any other way around this. The Xml could map to a function name (possibly even arguments) that you can invoke using reflection on the FormsModel to fill the ViewData or typed ViewDataModel with data.
The view for Form Index could generate a form from that xml through an HtmlHelper Extension that takes an XmlDocument.
Then when you (or asp.net mvc) binds your form to your ViewData your custom model binder is invoked it can inspect the current controller values to look for the formName and look up the corresponding xml that holds all the validation rules. The ModelBinder is then responsible for filling up ModelState with any runtime defined errors.
It's a hard task but when pulled off succesfully well worth it in my view :)
Update a better alternative to model data would be a very loose database schema as David Liddle suggests. I'd still go through the trouble of saving it as xml (or someother serialized format) and using that for generating the view and to hold validation rules for a custom ModelBinder so that you have more control on layout and validation of each field.
cottsak's answer is very attractive.
There are at least two client-side XForms engines. Here's one:
https://community.emc.com/community/edn/xmltech
I can't see huge advantages of generating XForms or any other "abstraction" over the HTML comparing with straight forward generation of HTML with "Web Forms 2.0" controls list for model like List<Tuple<Meta, Value>>. Note: on server side you in any case would be obligated to parse results manually to fit it to your structrures.
Searching for "next layer abstractions" is good for rapid development, but see, "generate code" (runtime or build-time) has its own specific. Usually the generating code of "lower layer" is the better solution than generating the "higher abstract layer" code.
So just go and wirte code that generate Web 2 Controls in #Foreach loop.

Resources