使用Web API和AngularJS保存表单数据(选择列表)

时间:2017-02-13 07:28:57

标签: javascript angularjs forms asp.net-web-api

我有一个显示人事数据的表单,并提供更新人员信息并将更改保存到我的数据库的功能。见下面的表格:

Figure 1. Personnel Information Form

绑定到文本框的字段我没有更新问题。但是,当涉及HTML选择列表(下拉列表)时,我无法保存新选择的值。

注意我可以在任意数量的文本框中进行更改,然后更改选择列表中的选项,并且表单的其余部分可以正常保存,而无需更改选择列表,所以它似乎没有任何失败。

我没有收到任何错误;但是,我在PUT之前看到了一个额外的OPTIONS请求,我不确定(所以关于为什么会这样做的任何其他提示也会受到赞赏)。

这是我的表格:

<form name="personForm" novalidate ng-controller="PersonnelEditCtrl as vm">
<fieldset class="col-md-4">
    <legend>Basic Personnel Information</legend>
    <div class="form-group row" ng-class="{'has-error':personForm.inputLastName.$invalid && personForm.inputLastName.$dirty}">
        <label class="col-md-3 control-label" for="inputLastName">Last Name</label>
        <div class="col-md-4">
            <input class="form-control" id="inputLastName" name="inputLastName" 
                   type="text" placeholder="Last Name (required)" 
                   ng-model="vm.person.lastName" required ng-minlength="1" ng-maxlength="30" />
        </div>
        <span class="help-block" has-error">
            <span ng-show="personForm.inputLastName.$error.required">
                Last name is required.
            </span>
            <span ng-show="person.form.inputLastName.$error.minlength">
                Last name must be at least 1 character in length.
            </span>
            <span ng-show="person.form.inputLastName.$error.maxlength">
                Last name cannot exceed 30 characters in length.
            </span>
        </span>
    </div>
    <div class="form-group row" ng-class="{'has-error':personForm.inputFirstName.$invalid && personForm.inputFirstName.$dirty}">
        <label class="col-md-3 control-label" for="inputFirstName">First Name</label>
        <div class="col-md-4">
            <input class="form-control" id="inputFirstName" name="inputFirstName" 
                   type="text" placeholder="First Name (required)" 
                   ng-model="vm.person.firstName" required ng-minlength="1" ng-maxlength="30" />
        </div>
        <span class="help-block" has-error">
            <span ng-show="personForm.inputFirstName.$error.required">
                First name is required.
            </span>
            <span ng-show="person.form.inputFirstName.$error.minlength">
                First name must be at least 1 character in length.
            </span>
            <span ng-show="person.form.inputFirstName.$error.maxlength">
                First name cannot exceed 30 characters in length.
            </span>
        </span>
    </div>
    <div class="form-group row" ng-class="{'has-error':personForm.inputMiddleInitial.$invalid && personForm.inputMiddleInitial.$dirty}">
        <label class="col-md-3 control-label" for="inputMiddleInitial">Middle Initial</label>
        <div class="col-md-4">
            <input class="form-control" id="inputMiddleInitial" name="inputMiddleInitial" 
                   type="text" placeholder="Middle Initial (required)" 
                   ng-model="vm.person.middleInitial" required ng-minlength="1" ng-maxlength="1" />
        </div>
        <span class="help-block" has-error">
            <span ng-show="personForm.inputMiddleInitial.$error.required">
                Middle initial is required.
            </span>
            <span ng-show="person.form.inputMiddleInitial.$error.minlength">
                Middle initial must be at least 1 character in length.
            </span>
            <span ng-show="person.form.inputMiddleInitial.$error.maxlength">
                Middle initial cannot exceed 1 characters in length.
            </span>
        </span>
    </div>
    <div class="form-group row">
        <label class="col-md-3 control-label" for="inputDateOfBirth">Date of Birth</label>
        <div class="col-md-4">
            <input class="form-control" ng-model="vm.person.dob" type="date" />
        </div>
    </div>
    <div class="form-group row">
        <label class="col-md-3 control-label" for="selectPayband">Payband</label>
        <div class="col-md-4">

            <select id="selectPayband" name="selectPayband" 
                    ng-model="vm.person.payband" ng-options="payband.name for payband in vm.paybands track by payband.id">
            </select>
        </div>
    </div>
    <div class="form-group row">
        <div class="col-md-4">
            <span>
                <button class="btn btn-primary" style="width:80px; margin-right:10px" 
                        ng-click="vm.submit()" ng-disabled="personForm.$invalid">Save</button>
            </span>
            <span>
                <button class="btn btn-default" style="width:70px" 
                        ng-click="vm.cancel(personForm)">Cancel</button>
            </span>
        </div>
    </div>
    <div class="form-group row" ng-show="vm.message">
        <div class="col-md-6">
            <pre style="font: inherit">{{ vm.message }}</pre>
        </div>
    </div>
</fieldset>

personnelEditCtrl.js

angular
.module("personnelService")
.controller("PersonnelEditCtrl",
             PersonnelEditCtrl);

function PersonnelEditCtrl(personnelResource, paybandResource, $filter) {
var vm = this;
vm.person = {};
vm.message = '';
vm.paybands = [];

paybandResource.query(function (data) {
    vm.paybands = $filter('orderBy')(data, 'Name');
});

personnelResource.get({ id: 2 },
    function (data) {
        vm.person = data;
        vm.person.dob = new Date(vm.person.dob);
        vm.originalPerson = angular.copy(data);
    });

if (vm.person && vm.person.personId) {
    vm.title = "Edit: " + vm.person.firstName + " " + vm.person.lastName;
}
else {
    vm.title = "New Person";
}

vm.submit = function () {
    vm.message = '';
    if (vm.person.personId) {
        vm.person.$update({ id: vm.person.personId },
            function (data) {
                vm.message = '... Save Complete';
            })
    }
    else {
        vm.person.$save(
            function (data) {
                vm.originalPerson = angular.copy(data);
                vm.message = '... Save Complete';
            })
    }
};

vm.cancel = function (editForm) {
    editForm.$setPristine();
    vm.person = angular.copy(vm.originalPerson);
    vm.message = "";
};
}

personnelResource.js

(function () {
"use strict";

angular
    .module("common.services")
    .factory("personnelResource",
            ["$resource",
             "appSettings",
                personnelResource])

function personnelResource($resource, appSettings) {
    return $resource(appSettings.serverPath + "/api/people/:id", null,
        {
            'update':{method:'PUT'}
        });
}
}());

paybandResource.js

(function () {
"use strict";

angular
    .module("common.services")
    .factory("paybandResource",
            ["$resource",
             "appSettings",
                paybandResource])

function paybandResource($resource, appSettings) {
    return $resource(appSettings.serverPath + "/api/paybands/:id");
}
}());

数据库结构:

dbo.People

PersonId : int (PK)
FirstName : string
MiddleInitial: string
LastName : string
DateOfBirth: datetime
PaybandId : int (FK)

dbo.Paybands

Id : int (PK)
Name : string

它可能与它无关,但我也会发布“人物”的Web API控制器代码:

using System.Linq;
using System.Web.Http;
using CPS.WebAPI.Models;
using System.Web.Http.Cors;
using System.Data.Entity;

namespace CPS.WebAPI.Controllers
{
[EnableCorsAttribute("http://localhost:53265", "*", "*")]
public class PeopleController : ApiController
{
    private CPS_Context db = new CPS_Context();

    public IQueryable<Person> GetPeople()
    {
        return db.Person;
    }

    public Person Get(int id)
    {
        Person person;

        if (id > 0)
        {
            var people = db.Person;
            person = people.FirstOrDefault(p => p.PersonId == id);
        }
        else
        {
            person = db.Person.Create();
        }

        return person;
    }

    public void Post([FromBody]Person person)
    {
        CPS_Context db = new CPS_Context();
        var newPerson = db.Person.Add(person);
        db.SaveChanges();
    }

    public void Put(int id, [FromBody]Person person)
    {
        CPS_Context db = new CPS_Context();
        db.Entry(person).State = EntityState.Modified;
        var updatedPerson = db.SaveChanges();
    }

    public void Delete(int id)
    {

    }
}
}

不要介意Web API的最低限度代码,我只是从头开始做所有事情,尽可能减少所有事情,以便让它在同一时间运行。

非常感谢您提供的帮助我在选择列表中保存所选选项的任何帮助。如果您有任何其他问题或需要更多信息,请告诉我 - 我尽量尽可能彻底。再次感谢任何人提供的任何帮助!

1 个答案:

答案 0 :(得分:5)

我的问题是JSON数据包含导航属性。更新失败,因为存在引用完整性冲突。

我的问题的解决方案是更新我的Entity Framework数据模型以从JSON中排除导航属性。我通过添加[JsonIgnore]属性这样做:

[ForeignKey("Payband")]
public virtual int PaybandId { get; set; }

[JsonIgnore]
public virtual Payband Payband { get; set; }