1

This was working when my JavaScript was in the same page as my cshtml file:

function SaveEntity() {
    // more code here
    alert(entity.FirstName);  // this shows that entity's properties have values
    $.post('/Home/Save', { entity: entity }, SaveComplete);
}

That code is now in a separate Index.js file. In my controller, the entity parameter isn't null, but all of its values are. Why would that happen now?

Controller signature:

public ActionResult Save(Entity entity)
{ // method here }

enter image description here

Edit - Fiddler Screenshot

enter image description here

enter image description here

Edit

This is the Entity class, generated by Entity Framework:

public partial class Entity
{
    public Entity()
    {
        this.Contacts = new HashSet<Contact>();
    }

    public int EntityId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }
    public string Company { get; set; }
    public string LastModifiedUser { get; set; }
    public Nullable<System.DateTime> LastModifiedTime { get; set; }
    public string Notes { get; set; }

    public virtual ICollection<Contact> Contacts { get; set; }
}

Edit

Full Index.js, with the full SaveEntity() method:

var _currentEntities;

    $(function () {
        // Hide the ID column (column 1)
        $('#tableContacts').dataTable({
            "aoColumnDefs": [
                { "bSearchable": false, "bVisible": false, "aTargets": [0] }
            ],
            "bLengthChange": false, // don't show the number of records to show per page
            "bFilter": false,  // don't show the search/filter box
            "iDisplayLength": 5
        });

        $('#waitImage').hide();
        // Show the letters of the alphabet, with a link to call GetEntries() for each of them.
        for (var i = 65; i <= 90; i++) {
            $('#headerAlphabet').append('<a href=\"#\" onclick=\"GetEntries(\''
                + String.fromCharCode(i) + '\')\">'
                + String.fromCharCode(i) + '</a> ');
        }
    });

            function GetEntries(firstLetter) {
                // code here
            }

            function EntriesReceived(entities) {
                // code here
            }

            function DisplayPerson(entityId) {
                // code here
            }

        function SaveEntity() {
            // Grab our entity
            var entity;
            for (var i = 0; i < _currentEntities.length; i++) {
                if (_currentEntities[i].EntityId == $('#txtEntityId').val()) {
                    entity = _currentEntities[i];
                    break;
                }
            }

            entity.FirstName = $('#txtFirstName').val();
            entity.LastName  = $('#txtLastName').val();
            entity.Address   = $('#txtAddress').val();
            entity.City      = $('#txtCity').val();
            entity.State     = $('#txtState').val();
            entity.ZipCode   = $('#txtZipCode').val();
            entity.Company   = $('#txtCompany').val();
            entity.Notes     = $('#txtNotes').val();

            alert(entity.FirstName);

            $.post('/Home/Save', { entity: entity }, SaveComplete);
        }

            function SaveComplete(saveStatus) {
                alert(saveStatus);
            }

            function CancelChanges() {
                alert('Cancel will be done here.');
            }
12
  • stupid question, but you do wrap that code in the $(document).ready(function () {..., right? Commented Mar 2, 2013 at 2:34
  • I do not. Is that necessary? Commented Mar 2, 2013 at 2:36
  • yes, because otherwise your page is not fully loaded and not all javascript has been instantiated, executed. Commented Mar 2, 2013 at 2:37
  • 1
    But that method doesn't get called until the page loads and the user makes changes and hits the save button. And the alert shows that entity does have its first name set. So, given that, I still need to wrap it? Commented Mar 2, 2013 at 2:38
  • well, not nessesarily, but it is hard to tell without seeing all of the js for that page. you could try to wrap it, though, and test. the symptoms you describe look like somewhere javascript does not get fully loaded Commented Mar 2, 2013 at 2:39

2 Answers 2

2

First, when doing any kind of ajax submission, you want to look at the actual request in an Http debugger, like Fiddler. You want to see if it's actually posting the values you think it is. That will help you isolate whether the problem is in your javascript, or on the server. Right now, you don't know.

See: This and This

Second, you should post your server side Entity definition.

EDIT:

This appears to be a problem with the way that jQuery serializes objects by default, which uses the bracket notation, which won't work with the default model binder. You have to use the traditional: true parameter that Dave mentions.

More about that Here. The following will solve your problem. the $.param method when used with the true parameter will force traditional serialization.

$.post('/Home/Save', $.param(entity, true), SaveComplete);. 
Sign up to request clarification or add additional context in comments.

16 Comments

I'll take a look with fiddler now. And I posted the definition of the Entity class. Thanks.
When using Fiddler, on the Inspectors tab, in the Body section, I see the entity and all of its values. Since I'm not familiar with Fiddler, I'm not sure what this means.
@BobHorn - post a screenshot of the fiddler inspector window that shows your post values.
I just posted it. +1 for the tips and the help, btw.
I can try that. I did make a change though. When I moved the JavaScript to its own page, this line no longer worked: $.post('@Url.Action("Save")', entity, SaveComplete); So I replaced it with $.post('/Home/Save', { entity: entity }, SaveComplete);
|
2

I hesitate, b/c my answer doesn't address why this would work from View yet fail from js file. But I would use an ajax vs post call to be able to set json and traditional:

 

$.ajax({
    type: 'POST',
    url: '/Home/Save',
    dataType: 'json',
    traditional: true,
    data: entity , //$.toJSON(data),
    success: function (data) {
          SaveComplete(data);
    }
});

5 Comments

Thanks. I can give that a shot. Your comment of $.toJSON(Data), am I supposed to do that instead of just data: entity?
@BobHorn, no don't this is from other code i copied and pasted. most coding errors come from that trap ;) Just use data: entity. if that fails, we may try toJson. either way I'm convinced its an encoding problem.
+1 for the tip, even though I haven't had a chance to try it yet. Appreciate the help...
Your suggestion has true being passed to SaveComplete(). Is there a way to get back to the way I had it, so that SaveComplete() gets the result from the controller method?
@BobHorn, yes you can get data back from .ajax(). see my revised answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.