【问题标题】:Managing HTTP requests and ViewModel in ASP.NET在 ASP.NET 中管理 HTTP 请求和 ViewModel
【发布时间】:2019-07-22 19:26:15
【问题描述】:

我有一个 CSHTML 页面,但我无法找到构建我的请求流的最佳方式,以及保持 ViewModel 中的内容与 View 中显示的内容的持久性。

我使用 ASP.NET Web 服务作为 API 将网站连接到数据库。这是我的控制器在调用视图之前填充 ViewModel 的方式:

[AllowAnonymous]
[Route("company/sites")]
public async Task<IActionResult> CompanySites()
{
    var client = _clientFactory.CreateClient("API");
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", HttpContext.Request.Cookies[Startup._tokenCookieName]);

    CompanyAccount user = JsonConvert.DeserializeObject<CompanyAccount>(HttpContext.Request.Cookies[Startup._companyInfoCookieName]);

    if (user == null)
    {
        return RedirectToAction("Index", "Company");
    }

    CompanySitesViewModel viewModel = new CompanySitesViewModel ();

    viewModel.LoggedInCompanyId = user.CompanyId;

    // Populate viewModel...

    return View(viewModel);
}   

视图模型:

public class CompanySitesViewModel 
{
    public List<CompanyDTO> AdministratedCompanies { get; set; }

    public CompanySitesViewModel ()
    {
        AdministratedCompanies = new List<CompanyDTO>();
    }
}

这是我从 View 中的 ViewModel 访问数据的地方之一:

...
@if (Model.AdministratedCompanies.Count > 0)
{
    <div class="list-group list-group-flush">
        @for (int i = 0; i < Model.AdministratedCompanies.Count; i++)
        {
            <button class="list-group-item">
                <div>
                    <h6>@Model.AdministratedCompanies[i].CompanyName</h6>
                    @if (@Model.AdministratedCompanies[i].CompanyCnpj != null)
                    {
                        <span><small class="text-muted">@@Model.AdministratedCompanies[i].CompanyCnpj</small></span>
                    }
                </div>
            </button>
        }
    </div>
}
...

当我想操作此列表中显示的数据时,我的问题就开始了。例如,我想从AdministratedCompanies 中删除一家公司。我目前正在直接对 API 进行 Ajax 调用,并在收到成功时强制刷新页面,以便在没有删除公司的情况下更新视图。

这是 Ajax 调用:

function deleteCurrentSite() {
    if (currentCompanyIdToDelete != null) {
        $.ajax({
            url: "@Startup._apiConnectionString" + "sites/" + currentCompanyIdToDelete ,
            type: "DELETE",    
            success: function (e) {
                showAlert('Company deleted. Refreshing page...', true);
                // Has to reload page to refresh site list
                document.location.reload(true);
            },
            error: function (e) {
                showAlert('Error deleting company.', false);
            },
            beforeSend: function (xhr) {
                xhr.setRequestHeader("Authorization", "Bearer " + '@Model.Token');
            }
        });
        return false;
    }
}

我有 React 开发背景,只需更改 state 并更新视图就非常容易,而且由于更改而不得不重新加载整个页面似乎非常不理想。

我有一些想法可以解决这个问题:

  1. 找到被删除公司的div,手动删除。不是最优的,当我想添加一个公司并且必须创建和附加组件时甚至更少。
  2. 让控制器存储 ViewModel 并让 Ajax 调用将我要删除的 ID 发送到控制器,然后控制器管理 API 调用。但据我发现,如果我使用RedirectToAction 或在删除后再次调用视图,页面仍然会刷新(尽管这似乎是让 Ajax 调用 API 的更好方法)。
  3. 找到了对该库 BeginCollectionItem 的一些引用,以在 View 和 ViewModel 之间创建更动态的绑定,但当我看到它在 7 年前更新时,我没有进一步调查。

那么在 View 和 ViewModel 之间创建动态绑定(包括 CRUD 操作和发生更改时重绘列表)的最佳方法是什么?

【问题讨论】:

  • 您可以从控制器方法返回 JSON,然后 javascript 将处理响应数据并相应地更新页面。那时您已经将视图和数据分开了......尽管控制器可以更新数据,而 javascript 可以更新视图。
  • @pcalkins 这需要我操作 HTML 追加和删除 div,对吧?我总是觉得这样做是错误的,我认为 CSHTML 语法和 HTML 助手会有更好的方法。
  • 如果您不想返回 JSON,您只需保留这些方法不变,并让 javascript 使用另一个 .cshtml 文件更新主 DIV。 (只是没有页眉/页脚的主要副本。)它将绑定到同一个控制器。我以前做过这个,只是在名称前加上“jq_”:“jq_pagename.cshtml”所以javascript用jq_页面更新主div。使用 partials,以便对部分的更新同时更新 main 和 jq_ 版本。

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


【解决方案1】:

这里是一些用于简单获取的 javascript (jQuery) 示例。处理程序传递“jq_pagename.cshtml”的 URL:

function DisplayError(jqXHR, textStatus, error) {
    errortext = error + jqXHR.responseText;

    $('#status').html('');
    $('#results').html(errortext);
}
function updateMainDiv(url) {
    $('#results').html('');
    data = "<img src='/images/waiting.gif'></img>";
    $('#status').html(data);
    $.get(url, function (data) {


        $("#results").html(data);
        $('#status').html('');
    }).fail(function (jqXHR, textStatus, error) {
        DisplayError(jqXHR, textStatus, error);
    });
}

对于这种技术,我通常将部分用于页面上的静态视图控件...搜索、顶级导航等...然后用于主要内容。主页包括那些,jq_ 页面不包括。 “结果” div 仅在主页中。您通过 javascript 将 GET 或 POST 发送到 jq_page 并通过 javascript 返回它们的 HTML。这样,可以使用完全相同的控制器来更新数据和视图。 (您只是截取返回的 HTML 并将其放在您喜欢的位置。)这是处理表单(onsubmit 或 onchange select 等)的示例:

function ProcessFormPost(formID, destURL) {

    formresult = $('#' + formID).serialize();

    $('#super').html('');
    data = "<img src='/images/waiting.gif'></img>";
    $('#status-super').html(data);
    $.post(destURL, formresult, function (data) {


        $("#super").html(data);
        $('#status-super').html('');
    }).fail(function (jqXHR, textStatus, error) {
        DisplaySuperError(jqXHR, textStatus, error);


    });

    return false;
}

【讨论】:

  • 挺有意思的,之前没想到。明天将对其进行测试,如果可行,我将接受它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-09
  • 2020-04-12
  • 2018-12-24
  • 2017-07-14
  • 2015-02-25
  • 1970-01-01
相关资源
最近更新 更多