你如何调试使用knockout.js的MVC 5应用程序?

时间:2016-08-26 16:49:18

标签: asp.net-mvc visual-studio-debugging

我正在使用Bootstrap和Knockout.js这本书#34; ASP.NET MVC 5"由杰米芒罗。我是一名经验丰富的程序员,但在MVC和Web开发方面都是业余爱好者。这是尝试学习如何做到这一点。

当我完成这本书时,我在我的应用程序中的某个地方犯了一个错误,所以现在我无法将提交或编辑保存到我的数据库中。而且我不知道如何弄清楚错误是什么。

示例代码仅提供一般错误。知道如何公开内部异常或错误消息会很有帮助。生成此通用错误标题的代码段如下:

self.errorSave = function () {
    $('.body-content').prepend('<div class="alert alert-danger"><strong>Error!</strong> There was an error saving the author.</div>');
}

我有两个问题,一个是特定的,一个是通用的。

具体来说:如何在网络浏览器中收到更详细的错误消息?

Generic:如何调试Web应用程序?我知道如何在不是Web应用程序的情况下在Visual Studio中进行调试,但是我无法捕获此错误。我的控制器或模型中的断点甚至我的表单都没有给我任何有用的信息。我还在Chrome和Internet Explorer中尝试过调试器,但还没有找到比#34;内部服务器错误:500&#34;更有用的东西。这并没有告诉我那么多。

可以在此处找到该书的代码示例:https://github.com/oreillymedia/ASP_NET-MVC-5-with-Bootstrap-and-Knockout_js

据我所知,这个例子有效。我没有运行它,因为我没有本地SQL Server,但如果我真的绝望,我必须设置它只是为了运行两组代码侧。将我的代码与它进行比较并没有指出我的错误。当然,这是一个完全有效的例子,我的代码只是最新的约1/3。

在我的Action方法中,第一个检查是ModelState.IsValid,它返回false。因此,没有保存。

    public ActionResult Create([Bind(Include = "Id,FirstName,LastName,Biography")] Author author)
    {
        if (ModelState.IsValid)
        {
            db.Authors.Add(author);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(author);
    }

模型绑定似乎无法正常工作。

在表单中,以下是First Name字段的设置方式:

        <div class="form-group">
            @Html.LabelFor(model => model.FirstName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { @class = "form-control" }, data_bind = "value: author.firstName" })
                @Html.ValidationMessageFor(model => model.FirstName, "", new { @class = "text-danger" })
            </div>
        </div>

在Model,Author.cs中:

public class Author
{
    [JsonProperty(PropertyName ="id")]
    public int Id { get; set; }

    [JsonProperty(PropertyName = "firstName")]
    [Display(Name = "First Name")]
    [Required]
    public string FirstName { get; set; }

    [JsonProperty(PropertyName = "lastName")]
    [Display(Name = "Last Name")]
    [Required]
    public string LastName { get; set; }

    [JsonProperty(PropertyName = "biography")]
    public string Biography { get; set; }

    [JsonProperty(PropertyName = "books")]
    public virtual ICollection<Book> Books { get; set; }
}

AuthorFormViewModel.js如下所示:

function AuthorFormViewModel(author) {

var self = this;

//variables to track state during saving
self.saveCompleted = ko.observable(false);
self.sending = ko.observable(false);

self.isCreating = author.id == 0;

//variable to track changes to model
self.author = {
    id: author.id,
    firstName: ko.observable(),
    lastName: ko.observable(),
    biography: ko.observable(),
};

self.validateAndSave = function (form) {
    if (!$(form).valid())
        return false;

    self.sending(true);

    //include anti forgery token
    self.author.__RequestVerificationToken = form[0].value;

    $.ajax({
        url: (self.isCreating) ? 'Create' : 'Edit',
        type: 'post',
        contentType: 'application/x-www-form-urlencoded',
        data: ko.toJS(self.author)
    })
    .success(self.successfulSave)
    .error(self.errorSave)
    .complete(function () { self.sending(false) });
};

self.successfulSave = function () {
    self.saveCompleted(true);

    $('.body-content').prepend('<div class="alert alert-success"><strong>Success!</strong> The author has been saved.</div>');
    setTimeout(function () {
        if ( self.isCreating )
            location.href = './'
        else
            location.href = '../'
    }, 1000);
}

self.errorSave = function () {
    $('.body-content').prepend('<div class="alert alert-danger"><strong>Error!</strong> There was an error saving the author.</div>');
}

}

最后,“创建/编辑”表单底部的脚本部分尝试以这种方式将所有这些组合在一起:

@section Scripts {
@Scripts.Render("~/bundles/jqueryval", "/Scripts/ViewModels/AuthorFormViewModel.js")
<script>
    var viewModel = new AuthorFormViewModel(@Html.HtmlConvertToJson(Model));
    ko.applyBindings(viewModel);
</script>
}

此外,从@ Html.HtmlConvertToJson(Model)返回的字符串显示格式正确。这是Create尝试返回的内容:     + str {   &#34; id&#34;:0,   &#34; firstName&#34;:null,   &#34; lastName&#34;:null,   &#34;传记&#34;:null,   &#34;书籍&#34;:null System.Web.HtmlString

调试时,看来是ko.ApplyBindings(viewModel);声明被完全跳过。也许在viewModel构造期间抛出了一个错误(@ Html.HtmlConvertToJson(Model)语句显示成功)但是我无法获得该错误令人沮丧,我无法弄清楚如何获得异常/断点/ call stack / something所以我可以调查。

1 个答案:

答案 0 :(得分:0)

我想跟进这个问题。

首先,我要感谢那些建议我从vanilla MVC开始的评论者。这是一个可靠的建议。在过去的几个月里,我度过了许多夜晚,我很高兴地说这是一个更好的方向。

在获得MVC的一些扎实的工作知识并建立一些小项目来学习它之后,我回到了这个问题并且能够解决它。

对于任何发现此问题的人来说,错误就在这里。

在AuthorFormViewModel中,我的代码使用Knockout将模型数据绑定到表单。

错误位于viewmodel的顶部,其中变量设置为可观察的Knockout绑定:

self.author = {
    id: author.id,
    firstName: ko.observable(),
    lastName: ko.observable(),
    biography: ko.observable(),
};

空变量!未绑定到从MVC模型绑定传入的作者模型。

应该是:

self.author = {
    id: author.id,
    firstName: ko.observable(author.firstName),
    lastName: ko.observable(author.lastName),
    biography: ko.observable(author.biography),
};

具有讽刺意味的是,错误根本不在MVC部分,但它确实让我学习了ASP.NET和MVC,我很感激。

我认为我没有获得这么多逻辑来解决这个微不足道的错误。