0

I have a problem with the binding of a complex model from a View that has updatable content, first things first, entites:

public partial class Diagnosis
{
    public Diagnosis()
    {
        this.DiagZones = new HashSet<DiagZone>();
        ...
    }

    public int diagnosisid { get; set; }
    public int playerid { get; set; }
    public int userid { get; set; }
    ...

    public virtual ICollection<DiagZone> DiagZones { get; set; }
}

My DiagZones Collection is the intermediate table between Diagnosis and Zones but it exist in my Model cause has more fields than the id's.

I have a Select control where you can select and unselect the Zones, when onchange fires, I Get a Partial View with an ajax call.

The code:

EditDiagnosis.cshtml

@model Gfire.Models.DiagnosisViewModel

<h2>
    @ViewBag.playername</h2>
@using (Html.BeginForm("EditDiagnosis", "Diagnosis", FormMethod.Post))
{    
    @Html.HiddenFor(d => d.Diagnosis.diagnosisid)   
    <table>
           ...
    </table>
    <table>
        <tr>
            <td>
                Zones:
            </td>
            <td>
                @Html.ListBoxFor(d => d.SelectedZones, new SelectList(Model.Zones, "zoneid", "description"), new
          {
              style = "width:305px;",
              onchange = "QualityMovement(this);",
              id = "lbZone",
              @class = "chzn-select"
          })
            </td>
            <td>
                ...
            </td>
        </tr>

    </table>

    <div id="qualitymovement">
        @Html.Partial("_QualityMovement", Model.Diagnosis.DiagZones)
    </div>

    <div>
        <input type="submit" value="Save" />
        &nbsp | &nbsp @Html.ActionLink("Cancel", "IndexDiagnosisPlayer", new { playerid = ViewBag.playerid })
    </div>
}

Partial View (_QualityMovement.cshtml):

@model List<Gfire.Domain.Entities.Diagnosis.DiagZone>

@if (Model.Count() != 0)
{
    <table>
        @foreach (var dz in Model)
        {
            <tr>
                <tr>
                    <td>
                        Flex:
                    </td>
                    <td>
                        @Html.TextBoxFor(d => dz.flex))
                    </td>
                </tr>
            </tr>


        }
    </table>
}

The Ajax.Get call:

<script type="text/javascript" language="javascript">

    function JointBalance(item) {
    ...
        $.ajax({
            url: '@Url.Action("GetJointBalances", "Diagnosis")',
            data: arrayToParamObject('zonesid', items),
            contentType: "application/json; charset=utf-8",
            success: function (data) {
                // Successful requests get here
                $("#jointbalance").html(data);

                $("#jointbalance").fadeIn('slow');
            },
            type: "GET",
            datatype: "json"
        });
    ...
    }
</script>

In server I have a Method that initialize a new list of DiagZones and update correctly the EditView.cshtml.

The problem comes when I try to Submit the complete Diagnosis object with all the fields and the list of DiagZones but my method:

[HttpPost]
public ActionResult EditDiagnosis(DiagnosisViewModel DiagnosisViewModel)
{
    if (ModelState.IsValid)
    {
        // Save the model
        ...

        return RedirectToAction("IndexDiagnosisPlayer", new { playerid = SessionHelper.Player.playerid });
    }
    else 
    {
        return View("EditDiagnosis", new { diagnosisid = DiagnosisViewModel.diagnosisid });
    }
}

My Model has empty the DiagnosisViewModel.DiagZones list.

I've tried to use EditorFor, pass the complete model to the partial View, add several forms... but it was useless, how can I bind that list to my model?

Thanks in advance.

UPDATE

Here is what the server side action is expecting:

[HttpGet]
public ActionResult GetJointBalances(int[] zonesid) { ... }

GET ajax request data looks like:

Request URL:http://localhost/Gfire.WebUI/Diagnosis/GetQualityMovement?zonesid=47
Request Method:GET
Status Code:200 OK
Request Headersview source
...
Connection:keep-alive
Content-Type:application/json; charset=utf-8
...
Referer:http://localhost/Gfire.WebUI/Diagnosis/EditDiagnosis?diagnosisid=0&playerid=23
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.152 Safari/537.22
X-Requested-With:XMLHttpRequest
Query String Parametersview sourceview URL encoded
zonesid:47
ApalanQ
  • 1
  • 3
  • Can you try via POST? Also, can you show the resulting JSON from `arrayToParamObject`? – Justin Mar 08 '13 at 14:33
  • I don't know what you mean with "via POST", the code for `arrayToParamObject` its simply a javascript function to parse the result and works ok, here is the javascript function: function arrayToParamObject(name, array) { var obj = []; for (var i = 0, len = array.length; i < len; i++) { obj.push({ name: name, value: array[i] }); } return obj; }; And this the Header of the server side: [HttpGet] public ActionResult GetJointBalances(int[] zonesid) { – ApalanQ Mar 08 '13 at 16:03
  • Show me what is being passed to the server (i.e. the JSON). It looks like your method is going to pass an array of name value pair objects and your action is expecting an array of integers. Either way, it would be much easier to just see the actual JSON being passed. Also... by "via POST" I mean, have your ajax request send the data via POST method so you would change `type: "GET"` to `type: "POST"`. On your action you would change `[HttpGet]` attribute to `[HttpPost]`. – Justin Mar 08 '13 at 16:54
  • In case you don't know how to view what is being passed to the server via Ajax... [look here](http://stackoverflow.com/a/3019085/945875) – Justin Mar 08 '13 at 16:58
  • BTW - I would simplify your question. The real problem is getting your data from the client to bind with your model on the server. Get rid of all the talk about the views. – Justin Mar 08 '13 at 17:04
  • Edit the question with the updated stuff I am asking about. It will be way easier to look at. – Justin Mar 08 '13 at 17:06
  • The array is passed correctly, generates the Html for the partial View and returns this to the page that updates the div with the new list of DiagZones, the updating in adding or deleting `Zones` in the main view is working but when I try to Save the `Diagnosis` object I don't obtain the binded list... – ApalanQ Mar 08 '13 at 17:13

1 Answers1

0

I found a temporal solution, not the best of course, but I thougth it would help to understand what I was trying to do and how to solve this. The problem, as Justin said, was binding the list<DiagZones> to main model, the Diagnosis object, following the posts of this:

I understand a little bit of the binding functionality, with that in mind I code my new PartialView _QualityMovement.cshtml:

@model List

@if (Model.Count() != 0)
{
    <table>
        @foreach (var dz in Model)
        {
            <tr>
                <tr>
                    <td>
                        Flex:
                    </td>
                    <td>
                        Html.TextBox("Diagnosis.DiagZones[" + i + "].ext", Model[i].ext)
                    </td>
                </tr>
            </tr>


        }
    </table>
}

It's a bad solution but at least I had my Model binded in server side. The problem is the abstraction made by the entity framework to my entities, as an ICollection so I cannot iterate as a List and found myself "casting" everywhere.

I suppose a better approach should be a CustomBinder to retrieve the data in the Request or type it in a neater and understandable way.

Thanks Justin for all the help you gave me.

Community
  • 1
  • 1
ApalanQ
  • 1
  • 3