【问题标题】:Loading partial page with Ajax not working as expected?使用 Ajax 加载部分页面未按预期工作?
【发布时间】:2016-05-06 05:54:33
【问题描述】:

我正在尝试 MVC 并使用 Ajax 加载部分视图。我找到了一堆不同的例子,但没有一个符合我正在寻找的东西,至少没有一个是我找到的。

我要做的是创建一个报告页面,顶部将有用户选择(开始/结束日期、支付代码、城市),然后我想用 jQuery/Ajax 调用控制器,获取数据,填充部分视图,并将其显示在用户选择的下方。

所以我现在会用 Javascript 抛出一个错误(我得到的只是“错误”的警报),但它会将部分页面作为一个完整的单独页面加载。我假设 AJAX 部分失败,但随后它移动到控制器 POST 的服务器端,它只是加载部分视图。我希望在<div id="reportResults"> 中加载部分视图。

我认为我首先犯的错误之一是我使用的是 MVC HTML.Form。该 POST 将发送到控制器,但我在想,因为我正在尝试使用 Ajax,所以我不会使用 MVC 表单?

我还有一个 ViewModel (TotalHoursReportVM) 用于最终用户访问页面时的用户选择,然后还有另一个 ViewModel (TotalHoursReportRecord) 用于获取实际报告的记录。由于我的主视图正在寻找 TotalHoursReportVM,如果我尝试将 TotalHoursReportRecordVM 传递给部分视图,显然会给我一个错误。所以,我不知道我应该结合这些,或者我什至应该结合吗?

我查看了很多文章并尝试了一些事情,以至于我对自己在做什么感到沮丧和困惑。希望有人可以为我提供一些启发或指出一个例子来看看。

这是我的主要视图。这只有一个开始/结束数据选择器、几个下拉列表和提交按钮。

@model PayrollReports.ViewModels.TotalHoursReportVM

@{
    ViewBag.Title = "Total Hours";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@section scripts
{
    <script src="@Url.Content("~/Scripts/Views/TotalHoursReport.js")"></script>
}

<h2>Total Hours Report</h2>

<div class="container">
    @using (Html.BeginForm("TotalHoursRun", "Report", FormMethod.Post))
    {
        @Html.AntiForgeryToken()
        @Html.ValidationSummary("Report creation was unsuccessful. Please correct the errors and try again.")

        <form class="form-horizontal" role="form">
            <div class="form-group">
                <div class="row voffset3">
                    <div class="col-md-2 text-left">
                        <div id="startDatepicker" class="input-group date">
                            <input class="datepicker form-control" type="text" />
                            <div class="input-group-addon">
                                <span class="glyphicon glyphicon-calendar"></span>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-2">
                        <div id="endDatepicker" class="input-group date">
                            <input type="text" class="form-control">
                            <div class="input-group-addon">
                                <div class="glyphicon glyphicon-calendar"></div>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-4"></div>
                    <div class="col-md-4"></div>
                </div>
            </div>
            <div class="form-group">
                <div class="row voffset3">
                    <div class="col-md-4 text-left">
                        @Html.DropDownListFor(m => m.SelectedPayCode,
                        new SelectList(Model.PayCodes, "PAY_CODE", "PAY_CODE"),
                        "-- Select Pay Code --",
                        new { style = "width:200px;height:30px" })

                    </div>
                    <div class="col-md-4">
                        <div id="templateGroup" style="display:none;">
                            Available templates<br />
                            <select id="dropdowntipo">
                                <option value="Exemplo1">Exemplo1</option>
                                <option value="Exemplo2">Exemplo2</option>
                                <option value="Exemplo3">Exemplo3</option>
                            </select>
                        </div>
                    </div>
                    <div class="col-md-4"></div>
                </div>
            </div>
            <div class="form-group">
                <div class="row voffset3">
                    <div class="col-md-4 text-left">
                        @Html.DropDownListFor(m => m.SelectedCityCode,
                        new SelectList(Model.CityCodes, "CityCode", "CityCode"),
                        "-- Select City --",
                        new { style = "width:200px;height:30px" })

                    </div>
                    <div class="col-md-4"></div>
                    <div class="col-md-4"></div>
                </div>
            </div>
            <div class="form-group">
                <div class="row voffset4">
                    <div class="col-md-4 text-left">                       
                        <button type="submit" id="btnRunReport" class="btn btn-primary">Run Report</button>
                        <button type="submit" id="btnTemplate" class="btn btn-default">Template</button>
                    </div>
                    <div class="col-md-4 text-left">
                    </div>
                    <div class="col-md-4"></div>
                </div>
            </div>
        </form>
    }


    <div id="reportResults">

    </div>
</div>

这是我的部分观点:

@model IEnumerable<PayrollReports.ViewModels.TotalHoursReportRecord>

<hr />
<div id="divgrid" style="margin-top: 15px;">
    @{
        var grid = new WebGrid(Model, canPage: true, rowsPerPage: 5, selectionFieldName: "selectedRow", ajaxUpdateContainerId: "gridContent");
        grid.Pager(WebGridPagerModes.NextPrevious);}
    <div id="gridContent">
        @grid.GetHtml(
                tableStyle: "webgrid-table",
                headerStyle: "webgrid-header",
                footerStyle: "webgrid-footer",
                alternatingRowStyle: "webgrid-alternating-row",
                selectedRowStyle: "webgrid-selected-row",
                rowStyle: "webgrid-row-style",
                columns: grid.Columns(
                    grid.Column("EmployeeId", "Employee", style: "id"),
                    grid.Column("FirstName", "First Name", style: "PName"),
                    grid.Column("LastName", "Last Name", style: "PName"),
                    grid.Column("PayCode", "Pay Code", style: "IName"),
                    grid.Column("PayHours", "Pay Hours", style: "Weight")
                    ))
    </div>
</div>

这是我的控制器:

namespace PayrollReports.Controllers
{
    public class ReportController : Controller
    {
        ReportRepository repo = new ReportRepository();


        // GET: Report
        public ActionResult TotalHours()
        {
            TotalHoursReportVM model = new TotalHoursReportVM();
            return View(model);
        }


        // POST: Report/TotalHoursRun
        [HttpPost]
        public ActionResult TotalHoursRun(DateTime? startDate, DateTime? endDate)
        {
            try
            {
                if (ModelState.IsValid)
                {
                    var data = repo.GetTotalHoursData();

                    return PartialView("_TotalHoursGrid", data);
                }
                return View();
            }
            catch
            {
                return View();
            }
        }
    }

这是我的存储库:

 public IEnumerable<TotalHoursReportRecord> GetTotalHoursData()
        {
            List<TotalHoursReportRecord> listHours = new List<TotalHoursReportRecord>();

            DateTime startDate = new DateTime(2015, 1, 4);
            DateTime endDate = System.DateTime.Today;


            using (DataContext db = new DataContext())
            {
                var payCodes = new string[] { "REG", "AST", "OT" };
                var companyCode = new string[] { "SM00", "EA00", "EX00" };
                listHours = (from h in db.HOURS
                             join e in db.SAP_EMPLOYEE on h.EMP_ID equals e.EMP
                             where companyCode.Contains(e.CO)
                             && h.OCCURRENCE_DATE >= startDate
                             && h.OCCURRENCE_DATE <= endDate
                             && payCodes.Contains(h.PAY_CODE)
                             select new TotalHoursReportRecord
                             {
                                 EmployeeId = h.EMP_ID,
                                 FirstName = e.FIRST_NAME,
                                 LastName = e.LAST_NAME,
                                 PayCode = h.PAY_CODE,
                                 PayHours = h.PAY_HOURS,
                                 OccurrenceDate = h.OCCURRENCE_DATE,
                                 CityCode = e.CITY_CODE
                             }).OrderBy(o => o.LastName)
                                .ThenBy(o => o.FirstName)
                                .ThenBy(o => o.OccurrenceDate)
                                .ThenBy(o => o.PayCode).ToList();
            }
            return listHours;
        }

这是我的视图模型

namespace PayrollReports.ViewModels
{
    public class TotalHoursReportVM
    {
        public int ReportID { get; set; }

        [Required]
        public DateTime StartDate { get; set; }

        [Required]
        public DateTime EndDate { get; set; }

        [Required]
        public string PayCode { get; set; }

        [Required]
        public string City { get; set; }

        public IEnumerable<APAY_CODES> PayCodes { get; set; }

        public int SelectedPayCode { get; set; }

        public IEnumerable<CityCodeVM> CityCodes { get; set; }

        public int SelectedCityCode { get; set; }

        public IEnumerable<TotalHoursReportRecord> TotalHoursReportRecord { get; set; }


        public TotalHoursReportVM()
        {
            var repo = new ReportRepository();
            PayCodes = repo.GetPayCodes();
            CityCodes = repo.GetCityCodes();
        }
    }

    public class CityCodeVM
    {
        public string CityCode { get; set; }
    }

    public class TotalHoursReportRecord
    {
        public string EmployeeId { get; set; }

        public string FirstName { get; set; }

        public string LastName { get; set; }

        public string PayCode { get; set; }

        public decimal PayHours { get; set; }    

        public DateTime OccurrenceDate { get; set; }

        public string CityCode { get; set; }

        public decimal TotalHours { get; set; }        
    }
}

这是我的 JavaScript:

$(document).ready(function () {

    //Datepicker
    var startDate = new Date();
    startDate.setDate(startDate.getDate() - 7);
    var endDate = new Date();

    $("#startDatepicker").datepicker("setDate", startDate);
    $("#startDatepicker").datepicker("update");
    $('#startDatepicker').datepicker().on('changeDate', function (ev) {
        $('#startDatepicker').datepicker('hide');
    });

    $("#endDatepicker").datepicker("setDate", endDate);
    $("#endDatepicker").datepicker("update");
    $('#endDatepicker').datepicker().on('changeDate', function (ev) {
        $('#endDatepicker').datepicker('hide');
    });


    $('#btnRunReport').click(function () {
        /*GET*/
        var start = $('#startDate').val();
        var end = $('#endDate').val();

        $.ajax({
            url: '/Report/TotalHoursRun',
            contentType: 'application/json; charset=utf-8',
            dataType: "html",
            type: "GET",
            data: { startDate: start, endDate: end },
            success: function (result) {
                alert(data);
            },
            error: function (xhr, status)
            {
                alert(status);
            }
        });
    });

【问题讨论】:

  • 继续阅读Ajax.BeginForm()
  • 您好,首先在您的 ajax 中输入:“GET”,但应该是“POST”或从控制器中删除 [HTTPPOST] 属性,其次是成功警报(数据);数据未定义,应为 $("#reportResults").html(result);
  • 您的第一个问题是带有id="btnRunReport" 的按钮是一个提交按钮,并且您尚未在$('#btnRunReport').click(function () { 中取消其默认操作(例如,通过添加return false; 作为最后一行代码)所以它同时执行 ajax 调用和正常提交。
  • 下一个问题是你需要删除contentType: 'application/json; charset=utf-8',(你没有对你的数据进行字符串化)。
  • 然后在您的 TotalHoursRun() 方法中,您有无意义的代码,例如 if (ModelState.IsValid) - 它始终有效(您没有发回模型!)而且您甚至不使用您发回的值所以不清楚你想做什么。

标签: jquery ajax asp.net-mvc asp.net-mvc-4


【解决方案1】:

你可以试试这样的:

改变

  <button type="submit" id="btnRunReport" class="btn btn-primary">Run Report</button>

<a class="btn btn-primary" href="#" id="btnRunReport" >Run Report</a>

在您的 ajax 调用更改中

   $('#btnRunReport').click(function (e) {
    /*GET*/
    e.preventDefault();
    var start = $('#startDate').val();
    var end = $('#endDate').val();

    $.ajax({
        url:  '@Url.Action("TotalHoursRun", "Report")',
        dataType: "html",
        type: "GET",
        data: { startDate: start, endDate: end },
        success: function (result) {
            $("#reportResults").html(result);
        },
        error: function (xhr, status)
        {
            alert(status);
        }
    });
});

在你的控制器中

   public ActionResult TotalHoursRun(DateTime? startDate, DateTime? endDate)
    {
       var data = repo.GetTotalHoursData();
       return PartialView("_TotalHoursGrid", data);
    }

【讨论】:

  • 谢谢,我已遵循所有这些建议。我将按钮设置为 ,将控制器更改为 HTTPGET,并让它获取数据并加载部分视图,并更改我的 Ajax 调用以匹配您的。但是,运行它时出现错误。在我的控制台中,我看到它说找不到“localhost/@Url.Action(%22TotalHoursRun%22,%22Report%22”。我复制并粘贴了方法名称,以确保我没有粗手指它,并且控制器名称肯定是“报告”。有什么建议吗?
  • 经过研究,这似乎与我使用的是外部 .js 文件有关。我会关注这个帖子,看看我能不能把它修好。 stackoverflow.com/questions/12514745/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多