Skip to main content
 首页 » 编程设计

c#之从 asp.net razor View 调用 ajax 请求

2024年02月25日38zhengyun_ustc

如何从返回 JSON 格式数据的 razor View 发起 ajax 请求(调用 Controller 操作)?

在我的 razor View 中单击操作链接后,页面执行发布请求,将页面重定向到/actionName,这当然不存在。

我也在使用 jQuery,但不确定如何从 razor View 获取数据,如果我使用 jQuery ajax 方法需要传递这些数据。

显示事件日志.cshtml

@{ ViewBag.Title = "Event Logs"; } 
@model IEnumerable 
<Application.Models.EventLogs> 
<table id="data-table" class="table display responsive" style="width:100%"> 
   <thead class="thead-colored thead-light"> 
      <tr> 
         <th>Time</th> 
         <th>Scheme</th> 
         <th>Serial Number</th> 
         <th>Batch</th> 
         <th>Exp Date</th> 
         <th>Product Code</th> 
         <th>Http Code</th> 
         <th>Is Confirmed?</th> 
         <th>Confirmation Date</th> 
         <th>Verify Pack</th> 
      </tr> 
   </thead> 
   <tbody> 
      @foreach (var item in Model) 
      { 
      <tr> 
         <td>@item.Timestamp</td> 
         <td>@item.ProductCodeScheme</td> 
         <td>@item.SerialNumber</td> 
         <td>@item.Batch</td> 
         <td>@item.ExpirationDate</td> 
         <td>@item.ProductCode</td> 
         <td>@item.HttpResponseCode</td> 
         <td>@item.ConfirmedParsed</td> 
         <td>@item.ConfirmedDate</td> 
         if (@item.HttpResponseCode == "202") 
         { 
         <td class="text-secondary">@Html.ActionLink("Verify Pack", "VerifyPack", "Home", new { ProductCodeScheme = @item.ProductCodeScheme, ProductCode = @item.ProductCode, SerialNumber = @item.SerialNumber, Batch = @item.Batch, ExpirationDate = @item.ExpirationDate, CommandStatusCode = 0 }, new { @class = "text-info" })</td> 
         } 
         else 
         { 
         <td class="text-secondary">Not Available</td> 
         } 
      </tr> 
      } 
   </tbody> 
</table> 
} 

Controller Action

[HttpPost] 
public ActionResult VerifyPack(string productCodeScheme, string productCode, string serialNumber, string batch, string expirationDate, int commandStatusCode, string orderTrackingNo = null) { 
    string TextAreaResult = string.Empty; 
    string TextAreaResultException = string.Empty; 
    string TextAreaResultHttpOperationCode = string.Empty; 
    string TextAreaResultHttpResponseCode = string.Empty; 
    string TextAreaResultHttpInformation = string.Empty; 
    string TextAreaResultHttpWarning = string.Empty; 
    string TextAreaResultState = string.Empty; 
    string RemoteIpAddress = string.Format("{0}", Request.UserHostAddress); 
 
    try { 
        using(SecureMediDatabase database = new SecureMediDatabase(this)) { 
            DatabaseFactory.setDatabase(database); 
            Request baseRequest = (Request) database.createRequest(Country); 
            ServiceThread serviceThread = new ServiceThread(0, null, Country); 
            serviceThread.attach(this); 
 
            baseRequest.setId(0); 
            baseRequest.setProductCodeScheme(productCodeScheme); 
            baseRequest.setRequestType(1); //single pack 
            baseRequest.setProductCode(productCode); 
            baseRequest.setSerialNumber(serialNumber); 
            baseRequest.setBatch(batch); 
            baseRequest.setExpirationDate(expirationDate); 
            baseRequest.setWorkstation(RemoteIpAddress); 
            baseRequest.setManualEntry(string.IsNullOrEmpty(expirationDate) || string.IsNullOrEmpty(batch)); 
 
            if (baseRequest.isManualEntry()) { 
                switch (commandStatusCode) { 
                    case 2: 
                    case 3: 
                        break; 
 
                    default: 
                        throw new NotSupportedException("This operation does not support manual entries!"); 
                } 
            } 
 
            switch (Country) { 
                case "SE": 
                    SecureMediRequestSE requestSE = (SecureMediRequestSE) baseRequest; 
                    requestSE.setUserId(@User.Identity.Name); 
                    requestSE.setCommandStatusCode(commandStatusCode); 
                    requestSE.OrderTrackingNumber = orderTrackingNo; 
                    break; 
 
                case "FI": 
                    SecureMediRequestFI requestFI = (SecureMediRequestFI) baseRequest; 
                    requestFI.setSubUserId(@User.Identity.Name); 
                    break; 
            } 
 
            serviceThread.RunRequest(control, baseRequest, apteekki); 
 
            TextAreaResult = string.Format("{0} {1} {2} {3} {4}", baseRequest.getResponseOperationCode(), baseRequest.getHttpResponseCode(), baseRequest.getHttpInformation(), baseRequest.getHttpWarning(), baseRequest.getResponseStatusCode()); 
 
            TextAreaResultHttpOperationCode = string.Format("{0}", baseRequest.getResponseOperationCode()); 
 
            TextAreaResultHttpResponseCode = string.Format("{0}", baseRequest.getHttpResponseCode()); 
 
            TextAreaResultHttpInformation = string.Format("{0}", baseRequest.getHttpInformation()); 
 
            TextAreaResultHttpWarning = string.Format("{0}", baseRequest.getHttpWarning()); 
 
            TextAreaResultState = string.Format("{0}", baseRequest.getResponseStatusCode()); 
        } 
    } catch (Exception exc) { 
        TextAreaResultException = "Exception: " + exc.Message; 
    } 
 
    return Json(new { 
        result = TextAreaResult, 
        httpOperationCode = TextAreaResultHttpOperationCode, 
        httpResponseCode = TextAreaResultHttpResponseCode, 
        httpInformation = TextAreaResultHttpInformation, 
        httpWarning = TextAreaResultHttpWarning, 
        state = TextAreaResultState, 
        exception = TextAreaResultException, 
        isSuccess = TextAreaResultHttpResponseCode == "200" || TextAreaResultHttpResponseCode == "202" 
    }); 
} 

基于答案的错误:

请您参考如下方法:

基本上@Html.ActionLink() helper 渲染带有属性的 anchor 标记 ( <a> ),默认使用刷新整个页面的 GET 请求,因此您需要添加 preventDefault()为了使用该元素的 AJAX 回调。如果 action 方法使用 HTTP GET 方法,您可以像这样对 anchor 链接的普通类执行简单的 AJAX 调用:

$('.text-info').on('click', function (e) { 
    e.preventDefault(); 
 
    var url = $(this).attr('href'); 
    $.get(url, function (response) { 
        // do something with AJAX response 
    }); 
}); 

然而,由于目标 Controller 操作标记为 [HttpPost] ,您需要从 href 中提取查询字符串参数具有附加功能的属性,并在带有 type: 'POST' 的 AJAX 调用中使用它们设置,或使用 $.post() :

$('.text-info').on('click', function (e) { 
    e.preventDefault(); // mandatory to prevent GET request 
 
    var url = $(this).attr('href'); 
 
    var pcs = getQueryStringParams(url, 'ProductCodeScheme'); 
    var pc = getQueryStringParams(url, 'ProductCode'); 
    var sn = getQueryStringParams(url, 'SerialNumber'); 
    var batch = getQueryStringParams(url, 'Batch'); 
    var expDate = getQueryStringParams(url, 'ExpirationDate'); 
    var csc = getQueryStringParams(url, 'CommandStatusCode'); 
 
    // create key-value pair for action method parameters 
    var obj = { ProductCodeScheme: pcs, ProductCode: pc, SerialNumber: sn, ... } 
 
    $.ajax({ 
        type: 'POST', 
        url: url.split('?')[0], // URL without query string, or use '@Url.Action("VerifyPack", "Home")' 
        data: obj, 
        dataType: 'json', // expects response as JSON 
        success: function (response) { 
            // do something with AJAX response 
        }, 
        error: function (xhr, status, err) { 
            // error handling 
        } 
    }); 
 
    // just make sure that the link is not redirecting 
    return false; 
}); 
 
function getQueryStringParams(url, name) { 
     return (RegExp(name + '=' + '(.+?)(&|$)').exec(url)||[,null])[1]; 
} 

实际上还有另一种方法可以从 anchor 标记调用 AJAX,如 @Ajax.ActionLink() ,取决于您的选择:

@Ajax.ActionLink("Verify Pack", "VerifyPack", "Home", new { ProductCodeScheme = @item.ProductCodeScheme, ProductCode = @item.ProductCode, SerialNumber = @item.SerialNumber, Batch = @item.Batch, ExpirationDate = @item.ExpirationDate, CommandStatusCode = 0 },  
                 new AjaxOptions { HttpMethod = "POST",  
                                   InsertionMode = InsertionMode.Replace,  
                                   UpdateTargetId = "targetElementId",  
                                   OnComplete = "onComplete();"  
                                 }, 
                 new { @class = "text-info" }) 

注意:

如果您需要处理来自同一个 Controller 的 AJAX 请求和普通请求,您可以使用 Request.IsAjaxRequest() 来区分它们。 (或 Core MVC 中的 Context.Request.Headers["X-Requested-With"] == "XMLHttpRequest")。