views:

38

answers:

1

Hello,

I have a partial view where I render, if the user has choosen an option, a button that permit the user to generate automatically a value for a certain field. Please give a look at this picture to understand what I mean:

alt text

This is achieved using the following markup on the partial view

<%= Html.LabelFor( model => model.IssueCode )%>
<br />
<% if ( Model.HasCodeGenerator ) { %>
    <%= Html.TextBoxFor( model => model.IssueCode, new { style = "width:120px;background-color:#eeeeee;border: solid 2px #dfdfdf", @readonly = "readonly" } )%>
    <% if (Model.ModelState == ModelStateEnum.Add) { %>
        <button id="codeGenerator" style="font-size: 0.7em;margin-right: 10px">Genera codice fascicolo</button>
    <% } %>
<% } else { %>
    <%= Html.TextBoxFor(model => model.IssueCode, new { style="width: 120px" })%>
<% } %>
<%= Html.ValidationMessageFor(model => model.IssueCode, "*")%>

As you can see I append always an Html.ValidationMessageFor() at the end of the input field and a ValidationSummary aut the end of the view.

When the user submits the form the first block of code executed by the action is the following

if ( !ModelState.IsValid ) {
    //Invalid - redisplay form with errors
    return PartialView( "IssueCodeGenerator", model );
}

and this is the result I am getting in all of the three cases

alt text

Why the markup code for the button disappear?

Thanks for helping!

1st EDIT:

After validation the IssueCode textbox loose it's readonly="readonly" attribute. This means that the first condition is not meet, I think....

2nd EDIT:

As per the Darin comment I am including

  1. The action that show the Partial View
  2. An extract of the partial that show that the ModelState variable is kept as an hidden control inside the form
  3. The controller Action called by the Partial
  4. The jQuery code that submit the partial

1 - This is the action that shows the partial

[HttpGet]
public ActionResult Create()
{
    IssueModel im = new IssueModel()
    {
        ModelState = ModelStateEnum.Add,
        FirmID = _firmManager.GetMyFirmID(),
        CreatedDate = DateTime.Now,
        LastUpdateDate = DateTime.Now,
        HasCodeGenerator = _optionManager.HasIssueCodeGenerator()
    };
    return PartialView("Issue", im);
}

2 - Extract of the partial Issue.ascx

<% using (Html.BeginForm("SaveOrDelete", "Issue", FormMethod.Post, new { id = "crudForm" })) { %>
    <%= Html.HiddenFor(model => model.FirmID) %>
    <%= Html.HiddenFor(model => model.IssueID) %>
    <%= Html.HiddenFor(model => model.ModelState) %>

3 - This is the controller action called when the form is submitted

[HttpPost]
public ActionResult SaveOrDelete( IssueModel model ) {
    if ( !ModelState.IsValid ) {
        //Invalid - redisplay form with errors
        return PartialView( "Issue", model );
    }

    try {
        Issue i = null;
        if ( model.ModelState == ModelStateEnum.Add )
            i = new Issue();
        else
            i = _manager.FindIssueByIssueID( model.IssueID );
        if ( model.ModelState != ModelStateEnum.Delete ) {
            _manager.BindIssueModel( i, model );
            if ( model.ModelState == ModelStateEnum.Add )
                i.FirmID = _contactManager.GetMyContact().FirmID;
            i.LastUpdateDate = DateTime.Now;
            _manager.SaveIssue( i );
        } else {
            _manager.DeleteIssue( i );
        }
        return PartialView( "ActionCompleted" );
    }
    catch ( Exception ex ) {
        return PartialView( "ActionError",
            new ActionErrorModel() { Message = ex.Message } );
    }
}

4 - This is the jQuery code that submit the form

$("#crudForm").submit(function(event) {
    event.preventDefault();
    $("#crudForm").block();
    $.ajax({
        type: "post",
        dataType: "html",
        url: "/Issue/SaveOrDelete",
        sync: true,
        data: $("#crudForm").serialize(),
        success: function(response) {
            $("#crudForm").parent().html('').html(response);
            $("#crudForm").unblock();
        },
        error: function(response) {
            $("#crudForm").unblock();
        }
    });
});

Hope that this would help in finding the problem. Thank you.

A: 

Because Model.ModelState == ModelStateEnum.Add evals to false?

MVC won't turn off your button html...


Even without seeing the form its pretty clear that Darin is right and your Modelstate enum is getting set to null.

jfar
@jfar: No. That's not true. ModelState evals to true as before submitting the form. I am just sending back the same model I have received. I know that MVC won't turn off my button but I suspect that something happens when validation occurs...
Lorenzo
@jfar: to be more precise... if I force that validation will not return false filling up all the fields I have checked that my data layer code executes the "Insert" branch. This means that Model.ModelState evals to ModelStateEnum.Add..
Lorenzo
@Lorenzo, instead of explaining all this please show your controller code because it is more than obvious that the problem here is related to the fact that your model properties are not properly populated and you are not entering the correct `if` branch. Don't think that if you return the same model to the view as the one you received as a parameter to your controller action this model is OK. If you don't have a corresponding field in your view to set for example the `ModelState` property it will simply take a default value.
Darin Dimitrov
@Darin: thank you for having time to look at this problem. I have done a 2nd EDIT on the question adding the code you have asked and even more to give you a deep view of this...
Lorenzo
@jfar: is pretty clear? Are you sure? Well... now give a look at the code so you can confirm what you're saying...
Lorenzo
@Lorenzo yup. Looks like some HTML element is binding the ModelState to something you don't expect. Post your view.
jfar
Lorenzo