ajax - ASP.NET MVC 部分 View 回发、不一致的更新和奇怪的行为

标签 ajax asp.net-mvc partial-views

我正在开发一个 ASP.Net MVC 应用程序,在尝试通过部分回发更新数据库中的数据时遇到了一个奇怪的问题。对于 HTTP、AJAX 等我还是个新手,所以我希望这是一个明显的错误。

基本上,当我尝试更新将内容区域链接到评估的表格时,更新有时有效,有时无效。奇怪的是,在我发布后,我直接从 MVC 应用程序查询数据库,只是为了确保确实进行了预期的更改(这就是所有 ViewBag.DebugInfo 在下面的代码中所做的事情)。在每种情况下,查询都会返回我希望看到的内容。但是,当我通过 SSMS 查询表时,我发现更改只是有时会发生。

从我的 MVC 应用程序对表的直接查询显示更新已完成,而我可以清楚地看到它没有通过 SSMS 进行,这是怎么回事?有无静默回滚之类的吗?这令人抓狂,我们将不胜感激任何帮助。

一些信息:

  • 当我在 MVC 之外从下面的assessmentContent 类运行“saveTheData”函数时,它总是成功的。
  • 第一次发布时更新总是成功。
  • 后续帖子的更新成功率只有大约一半。
  • 当更新不成功时,来自 MVC 应用程序的直接查询检查似乎确实表明更新已完全到达表。
  • 我几乎无法从失败中找出规律。也就是说,似乎每当我尝试更新到较高的 contentId 值时,都会成功,如果我尝试更新到较低的 contentId 值,则不会成功。例如,从值 1(数学)更新到 2(阅读)总是会成功,但反之则不会。如果它是来自父 View 的第一篇文章,或者如果它是通过 Linqpad 更新的,则此模式不会显现。
  • 我在数据库表上放置了插入、更新和删除触发器,这些触发器写入日志记录表以查看更改是否正在回滚。但失败时日志表中没有任何条目。但我也不知道回滚是否也会撤消触发器。
  • 我查询了 dbo.fn_dblog(),过滤了操作 = 'LOP_ABORT_XACT',但什么也没有(尽管我没有训练有素的眼睛来观察这个困难的 View )。

这是我的类,用于获取和更新数据:

public class assessmentContent {

    public int? assessmentId { get; set; }
    public List<short> baseline { get; set; } = new List<short>();
    public List<short> comparison { get; set; } = new List<short>();

    public assessmentContent() { if (assessmentId != null) refreshTheData(); }

    public assessmentContent(int assessmentId) {
        this.assessmentId = assessmentId;
        refreshTheData();
    }

    public void saveTheData() {

        List<short> upserts = comparison.Except(baseline).ToList();
        List<short> deletes = baseline.Except(comparison).ToList();

        foreach (var upsert in upserts)
            reval.ach.addAssessmentContent(assessmentId, upsert);

        foreach (var delete in deletes)
            reval.ach.deleteAssessmentContent(assessmentId, delete);

        refreshTheData();
    }

    void refreshTheData() {
        baseline = reval.ach.assessmentContent(assessmentId).ToList();
        comparison = reval.ach.assessmentContent(assessmentId).ToList();
    }

}

当我在 MVC 应用程序之外使用它时,逻辑工作正常。因此,例如,如果我通过 linqpad 使用它,就没有问题。我应该提到assessmentContent() 可以命名为“getAssessmentContent()”。

这是我的部分 View Controller ,以及一些相关代码:

public class ContentsModel {
    public int? assessmentId { get; set; }
    public List<short> comparison { get; set; }
}

public class ContentsController : Controller {

    public static string nl = System.Environment.NewLine;

    public ActionResult ContentsView(int assessmentId) {

        ViewBag.DebugInfo = new List<string>();

        var vm = new ContentsModel();
        vm.assessmentId = assessmentId;
        vm.comparison = reval.ach.assessmentContent(assessmentId).ToList();

        return View("~/Views/ach/Contents/ContentsView.cshtml", vm);
    }

    public ActionResult update(ContentsModel vm) {

        ViewBag.DebugInfo = new List<string>();
        sqlFetch();

        ViewBag.DebugInfo.Add($"VM Pased In {vm.assessmentId}  c{vm.comparison.intsJoin()}");
        sqlFetch();

        var crud = new crud.ach.assessmentContent((int)vm.assessmentId);
        ViewBag.DebugInfo.Add($"newly fetched CRUD {crud.assessmentId}  b{crud.baseline.intsJoin()}  c{crud.comparison.intsJoin()}");
        sqlFetch();

        crud.comparison = vm.comparison;
        ViewBag.DebugInfo.Add($"CRUD after crud_comparison = vm_comparison {crud.assessmentId}  b{crud.baseline.intsJoin()}  c{crud.comparison.intsJoin()}");
        sqlFetch();

        crud.saveTheData();
        ViewBag.DebugInfo.Add($"CRUD after save {crud.assessmentId}  b{crud.baseline.intsJoin()}  c{crud.comparison.intsJoin()}");
        sqlFetch();

        vm.comparison = crud.comparison;
        ViewBag.DebugInfo.Add($"VM after vm_comparison = crud_comparison {vm.assessmentId}  c{vm.comparison.intsJoin()}");
        sqlFetch();

        return PartialView("~/Views/ach/Contents/ContentsView.cshtml", vm);
    }

    void sqlFetch() {
        ViewBag.DebugInfo.Add(
                "SQL Fetch " +
                Sql.ExecuteOneColumn<short>("select contentId from ach.assessmentContent where assessmentId = 12", connections.research).intsJoin()
            );
    }

}

public static partial class extensions {

    public static string intsJoin(this IEnumerable<short> ints) {

        var strings = new List<string>();
        foreach (int i in ints)
            strings.Add(i.ToString());
        return string.Join(",", strings);
    }

}

我知道我可能没有在这里最好实现的 3 层架构或模型- View - Controller 结构。

您会注意到,在我的绝望中,我在模型的每个更改点都直接检查数据库表。

部分 View :

@model reval.Views.ach.Contents.ContentsModel
@using reval
@{Layout = "";}

<div id="contentDiv">

    <form id="contentForm">

        @Html.HiddenFor(m => m.assessmentId)

        @Html.ListBoxFor(
            m => m.comparison,
            new reval.ach.content()
                .GetEnumInfo()
                .toMultiSelectList(
                    v => v.Value,
                    d => d.DisplayName ?? d.Description ?? d.Name,
                    s => Model.comparison.Contains((short)s.Value)
                ),
            new { id = "contentListBox" }
        )

    </form>

    <br/>
    @foreach(string di in ViewBag.DebugInfo) {
        @Html.Label(di) 
        <br/>
    }

</div>

<script>

    $("#contentListBox").change(function () {

        $.ajax({

            url: "/Contents/update",
            type: "get",
            data: $("#contentForm").serialize(), 
            success: function (result) {
                $("#contentDiv").html(result);
            },
            error: function (request, status, error) {
                var wnd = window.open("about:blank", "", "_blank");
                wnd.document.write(request.responseText);
            }
        });
    })

</script>

最后,来自主视图的调用:

<div id="testDiv">
@if (Model.assessment != null && Model.assessment.assessmentId != null) {

    Html.RenderAction("ContentsView", "Contents", new { assessmentId = Model.assessment.assessmentId });   

}
</div>

最佳答案

您确定对数据库进行的事务已提交或完成吗?可能有其他事务同时进行,这些事务可能会回滚您正在进行的事务。

关于ajax - ASP.NET MVC 部分 View 回发、不一致的更新和奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38514580/

相关文章:

ruby-on-rails - Ruby on Rails——Heroku : Issue with votes button only in production

java - 使用 SQL 数据库中的值过滤 JSP 上的表值

c# - 如何禁用 Controller 上的按钮?

c# - mvc : Model. IsValid 在我使用 Request.Form 时不起作用

asp.net-mvc - 包恢复失败。在 MVC Core 中回滚 'myproject' 与 2017 年相比的软件包更改

jquery - 在部分 View 中定义 jquery 就绪事件

ruby-on-rails - 如何向 Rails 的部分渲染查找添加 View 路径?

javascript - Ajax 成功消息不起作用

javascript - 使用 jQuery 进行同步 ajax 调用的未弃用方法是什么?

javascript - 使用带有 ajax 和 jquery 的 js 模糊的 Laravel 电子邮件验证