JSON数据在C#Web API中解析不正确

JSON data not parsing correctly in C# Web API

本文关键字:不正确 API 数据 C#Web JSON      更新时间:2023-09-26

我目前正在网上学习如何使用Web API创建电话目录的教程。一切都很好,直到我开始使用javascript和knockout.js来绑定我的视图模型。现在没有任何数据加载到页面上。

当我试图通过http://localhost:{port_no}/api/Data/1这样的目录访问特定的电话目录id时,我的浏览器会尝试下载我存储数据的JSON数据。

有人能解释一下为什么会发生这种情况,以及为什么JSON数据没有被正确解析吗?

控制器类别:

namespace TelephoneDirectory.Controllers
{
    public class DataController : ApiController
    {
        public async Task<IEnumerable<TelephoneEntry>> Get()
        {
            using (var context = new DataContext())
            {
                return await context.TelephoneEntries.ToListAsync();
            }
        }
        public async Task<TelephoneEntry> Get(int id)
        {
            using (var context = new DataContext())
            {
                return await context.TelephoneEntries.FirstOrDefaultAsync(t => t.Id == id);
            }
        }

        public async Task<int> Post([FromBody] TelephoneEntry telephoneEntry)
        {
            using (var context = new DataContext())
            {
                if (telephoneEntry.Id == 0)
                {
                    context.Entry(telephoneEntry).State = EntityState.Added;
                }
                else
                {
                    context.Entry(telephoneEntry).State = EntityState.Modified;
                }
                await context.SaveChangesAsync();
                return telephoneEntry.Id;
            }
        }
    }
}

index.js(包含ko绑定的代码)

function TelephoneEntry(data) {
    var self = this;
    self.id = data.id;
    self.firstName = data.firstName;
    self.lastName = data.lastName;
    self.number = data.number;
}
function TelephoneViewModel() {
    var self = this;
    self.id = ko.observable(0);
    self.firstName = ko.observable('');
    self.lastName = ko.observable('');
    self.number = ko.observable('');
    self.addText = ko.observable('Add');
    self.resetText = ko.observable('Reset');
    self.selectedIndex = -1;
    self.add = function () {
        var entry = new TelephoneEntry({
            id: self.id(),
            firstName: self.firstName(),
            lastName: self.lastName(),
            number: self.number()
        });
        if (self.addText() == 'Add') {
            self.telephoneEntries.push(entry);
        }
        else {
            var oldTelephoneEntry = self.telephoneEntries()[self.selectedIndex];
            self.telephoneEntries.replace(oldTelephoneEntry, entry);
        }
        self.post(entry);
        self.reset();
    };
    self.reset = function () {
        self.id(0);
        self.firstName('');
        self.lastName('');
        self.number('');
        self.addText('Add');
        self.resetText('Reset');
        self.selectedIndex = -1;
    };
    self.load = function () {
        $.getJSON('http://localhost:16257/api/Data/', function (data) {
            $.each(data, function (index, item) {
                self.telephoneEntries.push(new TelephoneEntry({
                    id: item.id,
                    firstName: item.firstName,
                    lastName: item.lastName,
                    number: item.number
                }));
            });
        });
    };
    self.post = function (telephoneEntry) {
        $.post('http://localhost:16257/api/Data/', telephoneEntry, function (id) {
            telephoneEntry.id = id;
        });
    };
    self.telephoneEntries = ko.observableArray([]);
    self.load();
}
ko.applyBindings(new TelephoneViewModel());

WebApiConfig类:

namespace TelephoneDirectory.App_Start
{
    public class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();
            config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional });
            JsonMediaTypeFormatter jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
            jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        }
    }
}

Global.asax

public class Global : HttpApplication
    {
        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);
            Database.SetInitializer(new Initializer());
        }
    }

index.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <link href="Content/bootstrap.min.css" rel="stylesheet" />
    <link href="Content/site.css" rel="stylesheet" />
</head>
<body>
    <script src="Scripts/jquery-1.9.0.min.js"></script>
    <script src="Scripts/knockout-3.1.0.js"></script>
    <script src="Scripts/index.js"></script>
    <div class="container-narrow">
        <div class="row">
            <h1>Telephone Directory</h1>
        </div>
        <div class="row shaded padded">
            <div class="col-sm-3">
                <label for="firstName">First Name</label>
                <input id="firstName" name="firstName" type="text" class="form-control" data-bind="value: firstName" required="required" />
            </div>
            <div class="col-sm-3">
                <label for="lastName">Last Name</label>
                <input id="lastName" name="lastName" type="text" class="form-control" data-bind="value: lastName" required="required" />
            </div>
            <div class="col-sm-3">
                <label for="phoneNumber">Phone Number</label>
                <input id="phoneNumber" name="phoneNumber" type="text" class="form-control" data-bind="value: number" required="required" />
            </div>
            <div class="col-sm-12">
                <button id="add" name="add" type="submit" data-bind="click: add, text: addText">Add</button>
                <button id="reset" name="reset" type="reset" data-bind="click: reset, text: resetText">Reset</button>
            </div>
        </div>
    </div>
    <div class="container-narrow">
        <div class="row">
            <table class="table table-striped">
                <thead>
                    <tr>
                        <th>First Name</th>
                        <th>Last Name</th>
                        <th>Phone Number</th>
                        <th>&nbsp;</th>
                    </tr>
                </thead>
                <tbody data-bind="foreach: telephoneEntries">
                    <tr>
                        <td><span data-bind="text: firstName"></span></td>
                        <td><span data-bind="text: lastName"></span></td>
                        <td><span data-bind="text: number"></span></td>
                        <td>
                            <a href="#" data-bind="click: $parent.edit">Edit</a>&nbsp;<a href="#" data-bind="click: $parent.delete">Delete</a>
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>
    </div>
</body>
</html>{"id":1,"firstName":"Jon","lastName":"Preece","number":"4444"}

要在文档上设置绑定,请执行以下操作。

更改此

ko.applyBindings(new TelephoneViewModel());

到这个

$(function(){ 
    ko.applyBindings(new TelephoneViewModel());
});