ASP.NET MVC 4 - Update Model from View - asp.net-mvc

I'm playing around with ASP.NET MVC 4, but I have some problems with understanding. For better explanation I will use a simple "synthetic" situation.
Let's say I have model Person with 2 properties:
string Name
PersonType Type (e.g. Student, Employee, Military...)
Let's say in my controller I have private property Person. I can initialize this object in Index method, pass into View and build html page. Ok.
Now when user updates one of fields of person instance at the client side (he can input a new person name or select new person type using dropdown list), I want to update my model immediately. So, my general question is How can I achieve it?
Obvious solution for me: I can send an ajax request to controller from JS with new data. I thought that I can call controller's method UpdateName(string name) and update manually property Name with new data. BUT my person instance is NULL inside of this method! My second question is Why I can't access to initilized model object from other method? I think it's all about my bad understanding of client server interaction.
The final case of my situation: when user click's on the button "Save" I want to save created person into file on the server side, but I don't want to use any forms and receive all needed data just after clicking this button (because in my real task I can't use forms and also I can't receive all needed fields from html page after button clicking).
I have found the dirty solution. In JS I created another class Person with same properties. Now I can update instance of this class when I want and pass json data to server for saving it.
Is there any better solutions?

Its not that dirty to have javascript objects to represent your model. In fact thats how I do it. I use KnockoutJS to give me a client side model - which is essentially the MVVM pattern.
You are trying to use the MVC model in a way which you can't. However, the Knockout model you can use how you wish. You basically have a javascript representation of your server side model and once you are done with it you send it to the server.
In order for your server side methods to pick up your client side model you simply have to ensure the post request contains the data and as long as properties names are the same in the parameters of the method they will match themselves.

Why I can't access to initilized model object from other method?
Because it's not initialized anymore. Don't use the controller class to store persistent data across requests. The controller object is disposed after a request completes and then re-initialized on a new request. So anything that one action methods saves at the class level is gone when you get to another action method. Each request from the client to the server should be considered a fully isolated event, independent of any previous requests.
When you want to save your model, what you would do in that action is re-fetch it from the database, apply the changes, and save it back to the database.
but I don't want to use any forms
I'm not really sure what you mean here. Do you mean you want to use AJAX instead of POSTing the page directly? If so, that's fine. There are probably a number of tools out there to help you, personally I often just create a form anyway but instead of a submit button I have a plain button and add some JavaScript code (using jQuery) to serialize the form and perform an AJAX POST.
As long as the keys for the POST values map to your model fields in the same way they would in an out-of-the-box form, then your action method will still be able to receive the proper model type. On the server-side it doesn't matter if it's from an AJAX call or a normal POST. The difference, however, is that the response for an AJAX call should probably be in JSON format instead of responding with a view.
So instead of this:
return View(someModel);
You might have something like this:
return Json(someModel);

Related

avoid GET_ENTITY call on bindElement for data already loaded in get_entityset

I have a Master Detail Detail-Detail Application:
Master: List of Users
Detail: Table with Qualifications of the user
Detail-Detail: Form to Edit the Qualifications
In the Detail View I have all the informations I need for the Form in the Detail-Detail view.
when I get the path of the selected listItem in the Detail View and then do a bindElement in my DetailDetail View a new Request for GET_ENTITY is called in my backend. How can I avoid this call as I already have all the data I need in my Detail View?
I could work around this issue by using a local JSON Model for the data I want to edit, but as I would like to use .hasPendingChanges in my Edit View I guess I need to bind to the original oDataModel, but as mentioned would like to avoid the GET_ENTITY backend call.
When you are binding an OData context if you call an entity the you will end in a request. i.e:
Think in a /Order('123') context then you need to bind another entity like /Order('123')/Location this is going to trigger a network request but in the case of any data like ID /Order('123')/ID this dont do any network request because properties do not trigger requests.
OData Model
Requests to the back end are triggered by list bindings
(ODataListBinding), context bindings (ODataContextBinding), and CRUD
functions provided by the ODataModel. Property bindings
(ODataPropertyBindings) do not trigger requests.
As you said you can workaround it using a JSONModel but then you will need to maintain two models, create validations, etc.
Hope this clarification helps.

Best MVC way to handle multiple requests between view and model

I have a .net application with a Form layer, a DB model layer (entity framework) and a Controller layer between this two layers.
I need to handle this situation:
User presses a button to edit some params
The form needs to request some DB data that represents the current state of those params
Possibly, the user request could be rejected because is N/A to current situation, in this case an error message box should be shown
A modal form is shown, the user changes params and confirm
Changes are made in the DB model
That's pretty simple.
The fact is that, at point 4, we need some of the data we already processed at point 2.
In particular:
at point 2 we request some data to the DB model, that data is likely not to be in cache, so a SQL query is performed
that data is processed by a local LINQ
state of several checkboxes to show in the modal form is returned
at point 4 we need again LINQ processed data
since we came from the Form layer, we do not have that data anymore
therefore data is requested again to the DB model, but this time it's in cache
that data is processed again by local LINQ
Is it worth to re-load and re-process data to maintain the MVC pattern?
I don't know how it works exactly in VB.NET, but if we look at this problem in a pure "MVC" way (at least, how I understand it), something is not right.
In this step, when the click is done, the form call the controller (all action pass by the controller)
The controller then needs to do the validation. If it needs the database to do that, so be it. Then, it redirect the user to a view. (Should it be a message box or another form to enter data)
Here, the user do the change in the form and then click on a button to submit. In this button, you call the controller again (another function/action).
In the controller, you can do the needed validation and insert/update the data in the database via LINQ. Then, you can redirect to the view.
Since a lot of time could have passed between the step 2 and step 4 and that the data could have changed between the 2 calls, I think that doing the request 2 times is ok. Also, since they are 2 different function in the controller, I don't think you have the choice.
That's how I see it, but I can be wrong :)
EDIT
I didn't know that the query to the database were time consuming and that it was an issue.If the absolute goal is to NOT make the user wait twice since time is important in this application, I guess you could store the object that you get at step 2 in memory and retrieve it with the controller (with some kind of helper class). It's like doing the query in the database, but in the memory. If you use the repository pattern, then the programmer who's coding the logic in the controller will not even know that he's querying something else than the database since it's another level of abstraction. You could free the memory right after the step 4.
Oh I'm not 100% sure but the flow pattern in your question does not look right?
The usual procedure is to DISPLAY the DATA and have an edit button there with the dataview
So you may have something like
Function ShowAddressDetails(OwnerId as long) as ActionResult
And your ActionResult is usually a MODEL that is to be passed to the VIEW
maybe (keeping with the address record sample) something like...
Return View(AddressRecordModel)
where the address record is extracted from SQL DB using the OwnerId parameter
And in your VIEW where your EDIT button is,
You have at least two choices,
Those being
1. Reload data from SQL (used where data may have changed since last action)
2. Pass the already loaded Model (Used where the data hasnt changed)
which would mean tha you have either (or both) of the following
Function EditAddressDetails(OwnerId as long) as ActionResult
or
Function EditAddressDetails(Model as AddressRecordModel) as ActionResult
Alternatively you may have "CHILDACTION"s as opposed to "ACTION"'s
Also do not forget the following...
in a HTTP GET request, the model is passed from the CONTROLLER TO the VIEW
in a HTTP POST request the Model is passed from the VIEW to the CONTROLLER
So you should indeed have the model (data)?
Finally if the sequence is ONLY used by ONE user then the data should not have changed between requests UNLESS and EDIT/AMEND/UPDATE request was completed successfully.

How should I preserve and repopulate form data when opening a sub-form?

In an MVC4 project, I have a form that contains a partial view which is an index view of languages studied at school. It is a default type view template index, with Add, Delete, Edit links per row etc. When you Add or Edit, it opens an Add or Edit view for a Language. After e.g. adding a language, the updated partial view is returned.
My problem is that if the user opens the Language form, edits and captures on the main form will be lost. I can't just do an Ajax save before opening the Language form, as the main form may only be partially complete and fail validation. What I am thinking of doing though is using an AjaxPreserve action that takes a FormCollection, and stores it in session (o on disk, or anywhere) and therefore no model binding and server validation is performed.
I then have two problems: I will need to disable client validation before calling the AJAX action, and I will need to repopulate the main form using the FormCollection I saved earlier. I think there should surly be some jQuery voodoo to disable client validation, but I am completely stumped on repopulating the form.
ALTERNATE SOLUTION: Instead of using 'sub-forms', I can use editor templates, in pop-ip forms, where the FK IDs are not required, but that us only in certain cases, so my question still stands.
Could you use something like Knockout where you create javascript model and bind it to a grid/dialog edit/template view. I would transform the whole data to a JS model, bind it to a table/grid and then track all changes on the client side. When all is done, just serialize the whole model back to the server and update the data store.
If this is an acceptable scenario, it will save you a lot of trouble.
Familiarity with Knockout is required, but if you've used it before, you will be able to solve this in a very clean and efficient way.
This example on the Knockout website gives an idea of what I'm trying to suggest. Editing, deleting, adding is done on the client side until you send all of the data back to the server. You will need to track flags for each object to know if it's added, edited or deleted.
http://knockoutjs.com/examples/contactsEditor.html
Simple make the sub request for adding language using Ajax and repopulate the dropdown or what ever way you are accepting language on the main form on sucessfully save.
*This will save a lot of effort. *
Why don't you just use javascript?
E.g. You have main form, that stores some data. And when you need to add something specific like languages you open popup using partial view, allow user to fill form, but when user press submit you intercept action with js, save stuff to javascript array/object or whatever else and maybe store it in a hidden field of main form - for final submit
var newData = new Object();
newData.Field1 = $("#yourField1");
...
lanuageData.push(newData);
$("#languageContainer").val(JSON.stringify(languageData));
...
DataAnnotation validation works here as well like:
$.validator.unobtrusive.parse("your_partial_view_container");
When you need to edit some object that was already added to js array - open popup and fill it up with element of you js array. So basically you do all CRUD on client-side, saving changes only on final submit.
To make your code in a conrolller more clear you can use custom model binder which deserialize some string field from JSon to List or any other kind of object -> so it can be validated on server side.
Would saving your values to local storage be acceptable? What about using TempData?

How to validate data from a controller in a model?

I have data in my controller that is being received from another rails app and database (this has to be in the controller) I want to get this data so I can validate it in my model before allowing another step in a wizard (see my other question for some code examples)
My Problem is that I cannot directly grab this data from the controller in my model as this violates MVC.
My Question is how would I go about checking the controllers data in my Model?
Do I have to load this data / true - false response in a view and then link this to my Model? (I don't really want this to show in the view and haven't quite worked out how to do this)
Do I need to pass this data to a route i.e example/data.json and then check this in my Model? (I also haven't worked out how to use this data.json from there in my model)
Any help / steering in the right direction would be very useful. (also i cannot use a gem to do this)
At first, please be double double sure that you don't validate a model by data which it does not contain by itself. Model should validate its current state but not a way it came to this state (e.g. which user put a model to this state).
At second, you should never use controller methods in a model. If controller contains some business logic, extract that logic into a third class which will be used by both controller and model.
Moreover, you have a data in a controller and you have an access to the model, right?. Therefore, if you are in a controller method, for instance in a before filter or action, you could take that data and pass it to the model, like this:
def controller method
hey_model.is_this_correct?(data)
end
If you say that that data must be checked after controller has responded to a request (for example, at the next wizard step, i.e. at the next request), then you definitely must store that value somewhere between requests.
This is the very point of stateless HTTP. No data is saved between requests until you explicitly do that. You could store your value in cookies or in database.
I understand that the question was a while ago but for those who are still searching, I found the exact answer, how to pass the information from the controller to a model.
With this line everything is solved
var = request.env['target_model'].sudo().function_in_your_model(data)
var is a variable in case you need to handle that data in the controller, target_model is the model where you want to send the data, function_in_your_model is the function where you are going to handle the data already in the model, and inside this function you send the data that you need.

shortterm storage of user selection from form to controller

I am trying to conceive of a way to store a list of selected items to the session, for later use. I've googled and read examples for 2 hours now, and haven't found any examples that work.
The basic idea is this. User sees a list of items to act upon. User selects a number of them. User chooses action to perform. Controller takes list of selected items, and begins to act on them.
Am I thinking about this wrong? It makes sense to me to use an Ajax action to store the 'select/unselect' action on the session object. I really don't want an entire database object to handle this. I just want a simple list of selected objects. In classic ASP, I'd just have reacted to the selected items in a form post, but that doesn't seem right in asp.net mvc....
How do I construct this behavior (with or without the Ajax, but preferable without the DB access)?
I don't get it, why not bind directly an array of bools or something directly to your view's list of checkboxes? You can get them as parameters in your controller function and act upon them directly, with no middleman, they'd just be another POST value.
Or even better when you send in your list of items as part of your model, make them a structure that has a bool selected=false field that is bound to the checkbox next to the label, and you'll get the results back in your model directly.

Resources