Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to persist a complex object in the View while updating just a small portion

I have a feeling this could be a basic question!

I have a complex object ie a document object which contains properties that are lists of other objects. It has been created by deserializing some XML.

I would like to pass the entire Model to the View

Return ViewResult(MyDoc)

In the View some properties are edited. Control is then returned back to the Post Controller:

        [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Index(Document myDoc)

"myDoc" now just represents my Form's fields. I suspect this is ModelBinding at work. So I guess I need to persist my complex object in a hidden field(example would be great) or as a session object. However I am a bit confused how my updated field gets merged back into the persisted object(hidden or session).

like image 455
EdB Avatar asked Nov 23 '12 00:11

EdB


People also ask

How do you persist state in React after refresh?

To maintain state after a page refresh in React, we can save the state in session storage. const Comp = () => { const [count, setCount] = useState(1); useEffect(() => { setCount(JSON. parse(window. sessionStorage.

How do I update nested objects?

To update nested properties in a state object in React: Pass a function to setState to get access to the current state object. Use the spread syntax (...) to create a shallow copy of the object and the nested properties. Override the properties you need to update.

Which one is the correct way to update property of React state?

Approach 1: We can create a dummy object to perform operations on it (update properties that we want) then replace the component's state with the updated object. Approach 2: We can pass the old nested object using the spread operator and then override the particular properties of the nested object.

How do I set nested state?

you can set the nested property by cloning the current and patching the required segments of the data, for example: setState(current => { ... current, someProperty: { ... current.


2 Answers

Is storing that large object in the view entirely necessary?

The View seems to have no control over that content, so you probably don't want to send all that data to the View. It seems you are applying a mind-set based on ViewState, which doesn't really fit very well with MVC, IMHO.

Communication between the View and the Controller is done through ViewModels, and there's usually no need to store any large serialized data and making that go back and forth when interacting with the server.

Can't you create a ViewModel that represents only the useful data for the view (the fields), and get that data back in your Action by receiving the ViewModel during POST, and afterwards synchronize the information you obtained from the View with what you load from your XML only at that time?

like image 138
Pablo Romeo Avatar answered Oct 26 '22 21:10

Pablo Romeo


You are right, this is model binding at work.

The binding occurs almost automatically when you use HtmlHelpers such as :

@Html.TextboxFor(model => model.PropertyName)

This line actually creates something a little bit like this :

<input type="textbox" id="Modelobject_PropertyName" name="ModelObject.PropertyName" />

Then when you submit your form, the DefaultModelBinder is able to deserialize the POST value and create and object of the given type (at least it will try), if it can't find a corresponding entry, the property will be null and if an entry have no corresponding property, it will be ignored (unless you have other parameters).

You can read this article it's a little bit old, but it's still pretty accurate.

As an exemple:

Let's say you have a simple object :

public class IndexModel
{
    public string MyProperty { get; set; }
    public bool MyCheckbox { get; set; }
}

A simple controler :

public class TestingController : Controller
{
    [OutputCache(Duration=0, NoStore = true)]
    public ActionResult Index()
    {
        return View(new IndexModel { MyProperty = "hi" });
    }

    [HttpPost]
    [OutputCache(Duration=0, NoStore = true)]
    public ActionResult Index(IndexModel model)
    {
        model.MyProperty += "!";
        ModelState.Clear();
        return View(model);
    }
}

And a simple view :

@model MvcApp.Models.IndexModel

@using (Html.BeginForm())
{
    <div>
        @Html.LabelFor(model => model.MyProperty)<p />
        @Html.TextBoxFor(model => model.MyProperty) 
    </div>
    <div>
        @Html.LabelFor(model => model.MyCheckbox)<p />
        @Html.CheckBoxFor(model => model.MyCheckbox)
    </div> 

    <input type="submit" />
}

You will see, when you submit the form, that the model is recreated completely.

If you don't want to display the actual value of a property, but still need it persisted:

@Html.HiddenFor(model => model.MyProperty)

This will generate a hidden field that will be posted back and, therefor, persisted.

Happy coding !

like image 29
Yan Brunet Avatar answered Oct 26 '22 23:10

Yan Brunet