If Controller first validates ViewModel properties and then uses ViewModel properties, there may be small chance that ViewModel state may change to invalid between validation and usage, resulting in exceptional control flow.
Is there any common practice or pattern to ensure ViewModel state doesn't change and / or properties can be safely used after validation?
By keeping the state immutable, you can ensure that there is no change between validation and usage.
For instance:
class MyViewModel {
property MyImmutableState state;
}
class MyController {
private MyViewModel viewModel;
private doSomething() {
MyImmutableState state = viewModel.state;
if (isValid(state))
// because state is immutable, this is thread-safe
doSomething(state);
}
}
The key to making this work efficiently is that MyImmutableState should be not only immutable but also a persistent data structure (i.e. a data structure that keeps its old versions while being modified, typically via structural sharing). Libraries for such immutable collections exist in different languages.
Javascript: Immutable.js
.Net: System.Collections.Immutable
Java: http://www.javaslang.io/
Python: pyrsistent
Any function you apply to such a collection will return a new collection and leave the original one untouched. This way, the collection can be shared safely, without the need for locking.
Related
I'm working on a ASP.NET MVC system where you may click on a ajax link that will open a window (kendo window but it does not affect the situation) which a complex flow. To make this less of a nightmare to manage, I made a ViewModel (as I should) but this ViewModel is a complex object due to the complexity of the procedure.
There is anywhere from a single to 5 windows that asks various questions depending on a lot of conditions (including, but not limited to, what time you click the link, who you are, what schedule is attached to your account and, obviously, your previous answers in this flow).
The problem is that having a complex object, I cannot simply make #Html.HiddenFor(o=>o.XXX). So I proceeded to find an alternative and it led me with a single option, TempData. I'm really not a fan of dynamics and object types. I'd really like to have this View Model strongly typed.
What would be the best way to approach this?
Here is a case where using Session or TempData might make sense. Contrary to popular belief, you can make these somewhat strongly-typed. Not like a viewmodel, but you can avoid keychain messes by using extension methods.
For example, instead of doing something like this:
TempData["NestedVariable1"] = someObject;
...
var someObject = TempData["NestedVariable1"] as CustomType;
You can write extension methods to store these variables, and encapsulate the keys and casting in the extension methods.
public static class ComplexFlowExtensions
{
private static string Nv1Key = "temp_data_key";
public static void NestedVariable1(this TempData tempData, CustomType value)
{
// write the value to temp data
tempData[Nv1Key] = value;
}
public static CustomType NestedVariable1(this TempData tempData)
{
// read the value from temp data
return tempData[Nv1Key] as CustomType;
}
}
You can then read / write these values from either controllers or views like this:
TempData.NestedVariable1(someObject);
...
var someObject = TempData.NestedVariable1();
You could use the same pattern with Session as well. And instead of saving each individual scalar value in a separate variable, you should be able to store an entire nested object graph in the variable. Either that, or serialize it to JSON and store that, then deserialize when you get it back out. Either way, I think this beats a ton of hidden fields written out to your view's form.
I have started working out with Entity Framework (EF) for an MVC n-tier application. It would seem that very obvious that this being a web application (which is stateless), I would have to use detached object models. There is no ambiguity with doing an Add operation. However when doing an edit there are here are two ways
Fetch the original object in context, attach the updated object and
then save to database. Something like mentioned in answer to this
question
EF4 Context.ApplyCurrentValues does not update current values
Set individual modified properties explicitly using the IsModified property of individual fields of the object like
mentioned in this article
http://msdn.microsoft.com/en-us/data/jj592677.aspx
Method 1 has disadvantage of having to load object into memory from database each time an update needs to be performed.
Method 2 would require having to manually pass which fields to be set as IsModified to true from wherever the object an be updated. So for e.g. for each object, I may need to create a boolean collection object for each field of the object.
e.g.
SaveEntity(EntityClass e, EntityStateClass ec)
{
context.Entry(e).Property("Name").IsModified = ec.NameState;
context.SaveChanges();
}
class EntityStateClass{ public bool NameState;}
I would prefer method 2 simply for the sake of performance but I am hindered by the n-tier architecture and repository pattern I am using. My Repository interface restricts save method for any object to be
SaveEntity(EntityClass e);
So I cannot pass the "state" object. Context class is not available and should not be available outside DAL. So I cannot set property outside. Is there any "proper" way to achieve this ?
Note: Self-Tracking Entity is also out of question since I cannot send entities with state to client (the browser) since I am intent on keeping the html lightweight.
EDIT: After a lot of thinking, I am trying to use following mechanism to keep track of modified state for each field in my domain class
Declare a partial class for entity class.
For each field that is updateable, declare a boolean property like "IsModified_FieldName"
Set the "IsModified_FieldName" property when the field is set.
However for this I need Entity Framework to generate explicit properties for me instead of implicit properties that it auto-generates. Does EF provide an handle to do this ?
Here is sample code of what I am trying to achieve
//Save Method for class EntityClass.
SaveEntity(EntityClass e)
{
context.Entry(e).Property("Name").IsModified = e.IsModified_Name;
context.SaveChanges();
}
//EntityClass is class autogenerated by EF
public partial class EntityClass
{
//This is auto-generated property by EF
public string Name {get; set;}
/* This is what I would like EF to do
private string name;
public string Name
{
get {return Name;}
set {
name = value;
//this is what I would like to do
this.IsModified_Name = true;
};
}
*/
}
//This is another partial definition for EntityClass that I will provide
public partial class EntityClass
{
//This property will be set to true if "Name" is set
public bool IsModified_Name {get; set;}
}
PS: It seems the information I have provided is not sufficient and therefore there are no responses.
I am using DbContext (Database first model)
EF auto-generates the class files for me. So each time I update my database, the class files are regenerated.
To your concrete question: The entities are generated by a T4 template and it should be possible to modify this template (which is in text format) to generate the entities in a way you want to shape them.
But I have a few remarks about your concept:
In a web application data are usually changed by a user in a browser. To have a definite knowledge what really has been changed you need to track the changes in the browser (probably by some Javascript that sets flags in the data (a ViewModel for example) when a user edits a text box for instance).
If you don't track the changes in the browser what happens? The data get posted back to the server and you don't know at the server side (with MVC in a controller) which property has been changed. So, your only chance is to map all properties that has been posted back to your EntityClass and every property will be marked as Modified, no matter if the user really did a change or not. When you later call SaveChanges EF will write an UPDATE statement that involves all those properties and you have an unnecessary overhead that you you want to avoid.
So, what did you win by setting individual properties instead of setting the whole entity's state to Modified? In both cases you have marked all properties as Modified. Exceptions are partial changes of an entity, for example: You have a Customer entity that has a Name and City property and a view that only allows to edit the Name but not the City and a corresponding ViewModel that only contains a Name property. In this case your procedure would only mark the Name property of the Customer entity as Modified but not the City. You might save here a little bit because you don't save the City property value to the database. But you still save the Name even if it didn't change.
If you use solution 1 (ApplyCurrentValues) you have to load the entity first from the database, yes, but it would only mark the properties as Modified that really changed compared to their values in the database. If the user didn't change anything no UPDATE would be written at all.
Keep in mind that you are only at the beginning to implement your concept. There are other changes to the data that can happen in the browser than only scalar property changes, namely relationship changes. For example a user changes the relationship from an Order to a Customer or you have a view that has an Order and a collection of OrderItems and the user cannot only edit the Order header but also edit the OrderItems and remove and add new OrderItems. How do you want to recognize when the data come back from the browser to the server which collection item has been added and which has been removed - unless you track all those changes in the browser and send tracking information back to the server in addition to the actual data or unless you reload the Order and OrderItems from the database and merge the changes into the original entities from the database?
Personally I would vote for option 1 for these reasons:
You can use real POCOs that don't carry additional tracking information. (BTW: I have some doubt if you aren't reinventing the wheel by implementing your own tracking that EF change tracking proxies provide out of the box.)
You don't need to track changes in the browser which can become quite complex and will require Javascript in every Edit view to write change flags into hidden form fields or something.
You can use standard features of EF without having to implement your own tracking.
You are required to load entities from the database when you want to update an entity, that's true. But is this the real performance bottleneck in a web application where data have to run through the wire back and forth (and reflection (which isn't really known as to be fast) is involved by the model binder)? I have nothing said if your database is remote from the web server and connected by a 9600 baud modem. But otherwise, your plan is not only premature optimization, it is kind of premature architecture. You are starting to build a potentially complex architecture based on "it could be slow" to solve a performance problem that you actually don't know of whether it really exists.
OK, i am creating a web application. I am using MVC3. I have ViewModel for every view and also I have Data Model that supports viewModel and does the actuall CRUD operation in my sql table, while my viewModel validates and alters data as necessary.
Here is a question. The way I have been coding is
public class MyClassViewModel
{
public string member1{get;set;}
public int member2{get;set;}
public static GetAllMembers(MyClassViewModel obj, out string strErrMsg)
{
// code goes here, read operation
}
public static UpdateMyClass(MyClassViewModel obj, out string strErrMsg)
{
// code goes here, write operation.
}
}
Both My ViewModel and DataModels have been coded this way, My Controller on HttpPost just do something like this..
MyClassViewModel.UpdateMember(obj,out strErrMsg)
Since its mvc on every post it creates on a strongly typed view, a new object of my ViewModel, hence non static members are different and are not shared between sessions.
I am using Linq and therefore on each static method of my DataModel i use
var db = new MyApplicationDataContext()
to get my linq classes and work on them. This solves my open/close reader problems.
My question is, are there any issues regarding concurrency with this design? I know I might have problems in changing my data layer if it is not designed via interface, but I highly doubt that is necessary based on my application.
You are essentially using the factory design pattern. That's OK pattern to use for this; each static method has its own context, and that's OK too. You always have to worry about concurrency; however, the LINQ to SQL architecture has concurrency detection built in and throws a ChangeConflictException when a concurrent change has been made in reaction to this.
I would also highly recommend that you are disposing your contexts properly at the end of each static method call, because you could leave open connections to the database which can cause performance problems.
Also, another problem you may run into is interlinking data; you cannot link two objects together by reference that were created from different contexts. And in LINQ to SQL, there is no way to explicitly detach an object...
After my wonderings on the events registration (you can find here ViewModel Event Registration and ViewModel Lifetime), now I'm thinking about viewmodel tombstoning:
In case of Tombstoning, is the ViewModel serialization a good approach ?
I'm thinking about the case in which different viewmodels have a reference to the same class. In case of Viewmodels serialization and deserialization the referenced class instance could have duplicated instance, isn't it ?
Wouldn't be better to have specialized state classes whose unique purpose in to contain all the app data, everyviewmodel get data (i mean reference to the data) from there and update the data in there and the app think only to serialize those specialized class ?
Any experience on this subject is appreciated.
Regards
SkyG
Caliburn Micro has a lot of this built in to the framwork allowing you to save properties of a view model or the entire graph to both phone state and app settings. You just need to create a class and inherit from StorageHandler.
public class PivotPageModelStorage : StorageHandler<PivotPageViewModel>
{
public override void Configure()
{
this.ActiveItemIndex().InPhoneState().RestoreAfterViewLoad();
}
}
And to your other posted question. CM has a nice way of handling the forced view first approach on the phone. It allows you to do page navigation by specifying the VM and it will handle the rest. And as a bonus, if you specify parameters to pass CM will pull them off the query string and populate properties on the target VM.
public void GotoPageTwo()
{
navigationService.UriFor<PivotPageViewModel>().WithParam(x => x.NumberOfTabs, 5).Navigate();
}
I have a hierarchical model in MVC3. All my basic validation is working, but I have a special validation that I can't figure out how to implement.
In my particular tree-hierarchy model, I have a field which must be unique/not repeat the values in any of its ancestral nodes. In my case, peers do not have to be unique.
I've tried to inherit ValidationAttribute and use validationContext.Items to store a stack of parent nodes, but it doesn't seem to me that the validationContext.Items is shared between the validation of each level. I don't know how to recursively call the validation on each child correctly, if that is appropriate.
If I'm Validating a particular node, I need access to the ancestral nodes, or some stack I create of the ancestral nodes passed to each child.
The solution shouldn't interfere with other validators or binders and should provide field-level errors rather than root-model level errors. I also want to avoid ThreadStatic, reserved strings, and other magic tricks. Yes, the entire hierarchy is bound in a single view using this technique.
Thanks!
Could you create an action filter? This give you access to the modelstate and valueProvider so you could check the data and then adjust the Errors collection as necessary.
public class ValidateForUniqueAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// filterContext.Controller.ViewData.Model
// modelState[key].Errors.Add( .... )
}
}
[ValidateForUnique]
public class YourController : Controller