ajax POST not passing back correct data

67 views Asked by At

I am trying to pass back a json object back to my action in my device controller, this is then inserted into the database, however when I click the submit button on my form it seems to fire twice. Another problem is that my location field within the json object and pfID does not get sent back to the controller, the other fields get sent back properly. Here is my code:

$('#getDevice').unbind('click').bind('click', function (e) {
    e.stopPropagation();
    //anti forgery token
    //get the form
    var form = $('#addDeviceForm');
    //from the form get the antiforgerytoken
    var token = $('input[name="__RequestVerificationToken"]', form).val();

    var URL = 'Devices/PushIPForCollection';

    //Before this we need to build the model from the input the user has given us
    var device = {
        deviceID: ' ',
        ipAddress: $('#dIPAddress').val(),
        deviceName: $('#dDeviceName').val(),
        CreatedDate: ' ',
        UpdatedDate: ' ',
        CreatedBy: ' ',
        UpdatedBy: ' ',
        deviceSubGroupID: $('#dSubgroup option:selected').val(),
        subgroup: " ",
        companyID: ' ',
        hidden: ' ',
        pfID: $('#dpfID option:selected').val(),
        pf: ' ',
        location: JSON.stringify({
            'region': $('#dRegion').val() == null ? ' ' : $('#dRegion').val(),
            'country': $('#dCountry').val() == null ? ' ' : $('#dCountry').val(),
            'city': $('#dCity').val() == null ? ' ' : $('#dCity').val(),
            'building': $('#dBuilding').val() == null ? ' ' : $('#dBuilding').val(),
            'room': $('#dRoom').val() == null ? ' ' : $('#dRoom').val(),
            'rack': $('#dRack').val() == null ? ' ' : $('#dRack').val()
        })
    };

    alert(device.pfID);
    alert(device.location);

    $.ajax({
        url: URL,
        data: {
            __RequestVerificationToken: token,
            device: device
        },
        type: 'POST',
        success: function (result) {
        },
        error: function (jqXHR, textStatus, errorThrown) {
            alert("An error has occurred please contact us");
        }
    })
    $('#add-device').modal('hide');
    return false;
});

Where I alert my pfID it returns a string of "ba4475ef-0eed-441a-a77e-d733c288bf8e"

Here is my model:

public class Devices
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int deviceID { get; set; }

    [Display(Name="IP Address:"), StringLength(50)]
    public string ipAddress { get; set; }

    [Display(Name = "DeviceName:"), StringLength(50)]
    public string deviceName { get; set; }

    public DateTime? CreatedDate { get; set; }
    public DateTime? UpdatedDate { get; set; }
    public string CreatedBy { get; set; }
    public string UpdatedBy { get; set; }

    [Display(Name="Add to subgroup:")]
    public long? deviceSubGroupID { get; set; }

    [ForeignKey("deviceSubGroupID")]
    public DeviceSubGroup subgroup { get; set; }
    public string companyID { get; set; }
    public string hidden { get; set; }
    public string pfID { get; set; }
    [ForeignKey("pfID")]
    public PfHealth.Pf pf { get; set; }
    public string location { get; set; }
}

and here is my post method:

 public ActionResult PushIPForCollection(Devices device)
    {
        //Before committing to the database we need to check if the device already exists
        var checkIfDeviceExists = db.devices.Any(check => check.ipAddress == device.ipAddress);

        if (!checkIfDeviceExists)
        {
            if (ModelState.IsValid)
            {
                var userID = User.Identity.GetUserId();


                device.CreatedDate = DateTime.Now;
                device.UpdatedDate = DateTime.Now;
                device.CreatedBy = userID;
                device.UpdatedBy = userID;

                var subgroup = db.deviceSubGroups.Where(sub => sub.deviceSubID == device.deviceSubGroupID).FirstOrDefault();
                device.communityString = subgroup.snmpCommunityString;
                device.companyID = subgroup.companyID;

                db.devices.Add(device);
                db.SaveChanges();
            }

        }
        //Can change this to get json in order to let to view know what message to display to the user.
        return RedirectToAction("index");
    }

and here is my form in the view:

<div class="modal fade" id="add-device" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
    <div class="modal-content">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            <h4 class="modal-title" id="add-device-Label"><strong>ADD DEVICE</strong></h4><!--add depending on which panel you have clicked-->
        </div>
        <div class="modal-body" id="add-device-body">
            <!--Depending on which panel insert content-->
            @using (Html.BeginForm("PushIPForCollection", "Devices", FormMethod.Post, new { id = "addDeviceForm" }))
            {
                @Html.AntiForgeryToken()

                <hr />
                <div class="form-horizontal">
                    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
                    <div class="form-group">
                        <div class="col-md-3">
                            @Html.LabelFor(m => m.device.ipAddress, new { @class = "col-md-2 control-label"})
                        </div>
                        <div class="col-md-9">
                            @Html.TextBoxFor(m => m.device.ipAddress, new { @class = "form-control", @id = "dIPAddress" })
                        </div>
                    </div>

                    <div class="form-group">
                        <div class="col-md-3">
                            @Html.LabelFor(m => m.device.deviceName, new { @class = "col-md-2 control-label" })
                        </div>
                        <div class="col-md-9">
                            @Html.TextBoxFor(m => m.device.deviceName, new { @class = "form-control", @id = "dDeviceName" })
                        </div>
                    </div>

                    <div class="form-group">
                        <div class="col-md-3">
                            @Html.LabelFor(m => m.device.deviceSubGroupID, new { @class = "col-md-2 control-label" })
                        </div>
                        <div class="col-md-9">
                            @Html.DropDownListFor(m => m.device.deviceSubGroupID, (IEnumerable<SelectListItem>)ViewBag.subGroups, "None", new { @id = "dSubgroup" })
                            @Html.ValidationMessageFor(m => m.device.deviceSubGroupID, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group">
                        <div class="col-md-3">
                            @Html.Label("Region:")
                        </div>
                        <div class="col-md-9">
                            @Html.TextBox("Region", "", new { @class = "form-control", @id = "dRegion" })
                        </div>
                    </div>

                    <div class="form-group">
                        <div class="col-md-3">
                            @Html.Label("Country:")
                        </div>
                        <div class="col-md-9">
                            @Html.TextBox("Country", "", new { @class = "form-control", @id = "dCountry" })
                        </div>
                    </div>

                    <div class="form-group">
                        <div class="col-md-3">
                            @Html.Label("City:")
                        </div>
                        <div class="col-md-9">
                            @Html.TextBox("City", "", new { @class = "form-control", @id = "dCity" })
                        </div>
                    </div>

                    <div class="form-group">
                        <div class="col-md-3">
                            @Html.Label("Building:")
                        </div>
                        <div class="col-md-9">
                            @Html.TextBox("Building", "", new { @class = "form-control", @id = "dBuilding" })
                        </div>
                    </div>

                    <div class="form-group">
                        <div class="col-md-3">
                            @Html.Label("Room:")
                        </div>
                        <div class="col-md-9">
                            @Html.TextBox("Room", "", new { @class = "form-control", @id = "dRoom" })
                        </div>
                    </div>

                    <div class="form-group">
                        <div class="col-md-3">
                            @Html.Label("Rack:")
                        </div>
                        <div class="col-md-9">
                            @Html.TextBox("Rack", "", new { @class = "form-control", @id = "dRack" })
                        </div>
                    </div>

                    <div class="form-group">
                        <div class="col-md-3">
                            @Html.LabelFor(model=>model.device.pfID)
                        </div>
                        <div class="col-md-9">
                            @Html.DropDownListFor(m => m.device.pfID, (IEnumerable<SelectListItem>)ViewBag.pathfinders, "None", new { @id = "dpfID" })
                            @Html.ValidationMessageFor(m => m.device.pfID, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group">
                        <div class="modal-footer">
                            <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                            <button id="getDevice" type="submit" value="CreateGroups" data-loading-text="Loading..." class="btn btn-primary">Save changes</button>
                        </div>
                    </div>
                </div>

            }
        </div>
    </div>
</div>

1

There are 1 answers

3
Shyju On

You do not need to create the javascript object manually, You may use jQuery serialize method to serialize the entire form and send it via ajax as long as the form field names matches with the param names/model property names in the HttpPost action method.

You may create a view model specific to the view.

public class CreateDeviceVm
{
   public string DeviceId {set;get;}
   public string IPAddress {set;get;}
   public int DeviceSubGroupId {set;get;}
   public List<SelectListItem> DeviceSubGroups {set;get;}
   public string City {set;get;}
   public string Room {set;get;}
   //Add properties NEEDED FOR THE VIEW. 
}

In your GET action, create an object of this view model, assign the DeviceSubGroups property and send to the view.

public ActionResult Create()
{
  var vm = new CreateDeviceVm();
  vm.DeviceSubGroups = db.DeviceSubGroups
                  .Select(s=> new SelectLisItem { Value=s.Id.ToString(),
                                                  Text = s.Name }).ToList();

  return View(vm);
}

And in your view, which is strongly typed to the view model, @model CreateDeviceVm

@using(Html.BeginForm())
{
  <label>DeviceId</label>
  @Html.TextBoxFor(s=>s.DeviceId)
  <label>IP Address</label>
  @Html.TextBoxFor(s=>s.IPAddress)
  <label>Sub group</label>
  @Html.DropDownListFor(s=>s.DeviceSubGroups,Model.DeviceSubGroups,"Select")
  <label>City</label>
  @Html.TextBoxFor(s=>s.City)
  <label>Room</label>
  @Html.TextBoxFor(s=>s.Room)
  <input type="submit" id="btnSave" />
}

Now you can add some javascript to listen to the click event on the submit button, get a reference to the form, serialize it and send to the server using jQuery ajax.

$(function(){    
  $("#btnSave").click(function(e){    
    e.preventDefault();

    var _f=$(this).closest("form");
    $.post(_f.attr("action")._f.serialize(),function(res){
        //check res and do something
    });    
  });    
});

And in your HttpPost action method,

[HttpPost]
public ActionResult Create(CreateDeviceVm model)
{
   var exists= db.devices.Any(x=> x.ipAddress == model.ipAddress);
   if (!exists)
   {
      var d= new Device();
      d.IpAddress=model.IPAddress;
      d.DeviceSubGroupId=model.DeviceSubGrouId;
      //Map other properties as well.

      db.Devices.Add(d);
      db.SaveChanges();
      return Json( new { status="success"});
   }
   return Json( new { status="failed"});
}