如何从 jQuery 调用 C# 静态方法

Posted

技术标签:

【中文标题】如何从 jQuery 调用 C# 静态方法【英文标题】:How to call a C# static method from jQuery 【发布时间】:2018-03-15 06:30:28 【问题描述】:

我看到一些文章展示了如何使用 Microsoft 的 [WebMethod] 从 javascript 调用 C# 方法,用于 Web 窗体应用程序。我想对 ASP.NET MVC 应用程序做同样的事情。我有一个返回翻译数据的 C# 静态方法:

public static string Translate(string word)

  return langRepo.Translate(word);

上述函数在服务器端代码中运行良好。但是,我想将相同的代码扩展到客户端。理想情况下,我想创建一个这样的 jQuery 函数:

function Translate(word) 
  //call C# translate method and return result

并像这样使用它:

"<hr /><h5>" + Translate(heading) + "</h5>";

我该怎么做?

【问题讨论】:

需要使用ajax调用服务端方法 我已经试过了。它不起作用 你没有正确尝试:) 添加您的 ajax 代码,我们将能够纠正它。 请将代码、错误和数据添加为文本 (using code formatting),而不是图像。图片:A)不允许我们复制粘贴代码/错误/数据进行测试; B) 不允许根据代码/错误/数据内容进行搜索;和many more reasons。一般来说,文本格式的代码/错误/数据>>>>作为图像的代码/错误/数据>>没有。只有在除了代码格式的文本之外,如果图像添加了一些重要的东西,而不仅仅是文本代码/错误/数据传达的内容,则应该使用图像。 【参考方案1】:

执行以下操作:

在服务器端的函数顶部添加[WebMethod]。 来自客户端的调用应该类似于以下 sn-p:

提示:类型应该是“POST”类型。完整示例请查看this。

function Translate(word)
  // Type of data passed should match the function's parameters
  var data = word: word;
  $.ajax(
    type: "POST",
    url: "pageName.aspx/Translate",
    data: data,
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    error: function (XMLHttpRequest, textStatus, errorThrown) 
      alert("Request: " + XMLHttpRequest.toString() + "\n\nStatus: " + textStatus + "\n\nError: " + errorThrown);
    ,
    success: function (response) 
      // Here you can assign response to tags.
      // If response was empty, try response.d.
      $("#id").html(response);

    
  );

如果您使用的是 ASP.NET MVC 应用程序,则可以改用 [HttpGet] 并以 JSON 格式从您的函数 (Action) 返回结果,因为我们在 Ajax 请求中指定了我们期望的 dataType: "json"

下面是一个例子:

[HttpGet]
public ActionResult Translate(String word)

  var resultWord = ModelInit.repo.TranslateItem(word);
  return Json(new result = resultWord, JsonRequestBehavior.AllowGet);

在您的 Ajax 调用的成功处理程序中,通过访问 result 属性获取值:

success: function (response) 
  // Here you can assign response to tags
  $("#id").html(response.result);

【讨论】:

不幸的是,这不起作用。您假设我的函数位于“.aspx”页面内。我正在使用 MVC(这里没有 .aspx 页面)。我创建了一个“模仿”函数调用的 Web API,但即使这对我也不起作用。 我的函数在另一个我称之为“App.Services.Helpers”的程序集中: namespace App.Services.Helpers public static class Utility public static string CapitalizeFirst(string word) // 检查空字符串。 if (string.IsNullOrEmpty(word)) return string.Empty; // 返回 char 和 concat 子字符串。返回 char.ToUpper(word[0]) + word.Substring(1); [WebMethod] public static string Translate(string word) return ModelInit.repo.TranslateItem(word); 也许我可以换一种方式...假设我创建了一个 Web API,我可以在其中传递单词,它会像这样为我翻译它:/api/translate/title 和这个API 返回一个字符串:“título”。我怎样才能抓住这个结果并像这样使用它:heading = "
" + translateWord + "
";?
您的问题不够清楚,因为您提到了“网络表单”应用程序,这就是我写这个答案的原因。如果是 MVC 应用程序,则无需使用 [WebMethod] 进行装饰 .. 而是使用 [HttpGet] 并在您的函数内部进行装饰 - return Json(new id = 10, title="test");【参考方案2】:

试试下面的。首先是一个 C# 控制器操作,它将返回一个 json,然后从 jQuery 方法调用控制器操作。

public class LanguageController : Controller

    [HttpGet]
    public JsonResult Translate(string word) 
    
        var translatedWord = langRepo.Translate(word);
        return Json(translatedWord, JsonRequestBehavior.AllowGet); 
    

jQuery 方法:

function Translate(word) 
    $.ajax(
        type: "GET",
        url: "/Language/Translate",
        data: word: word,
        dataType: "json",
        cache: false,
        success: function (data) 
            if(data.length == 0) 
                alert("Cannot translate.");
            
            else 
                // Get the translated word
                var translatedWord = data.translatedWord;

                // Update the DOM element (label) with translated word 
                $("#translatedWord").text(translatedWord);
            
        
    );

【讨论】:

【参考方案3】:

在我多年的编程生涯中,我第一次不得不将 AJAX 调用更改为同步,以使其按我想要的方式工作。所需要的只是将 "async: false" 属性添加到 AJAX 调用。这样,AJAX 调用就被视为任何其他同步函数:

function Translate(word) 
    var Url = "/api/translate/" + word;
    var translated;

    $.ajax(
        type: "GET",
        url: Url,
        dataType: "json",
        cache: false,
        async: false,
        success: function (response, status, xhr) 
            translated = response.translatedWord;
        ,
        error: function (jqXhr, textStatus, errorThrown) 
            var error = CapitalizeFirst(textStatus) + ": " + errorThrown + " - " + jqXhr.responseText;
            bootbox.alert(error);
        
    );

    return translated;

对于那些想将其作为项目解决方案实施的人,请再想一想!使 AJAX 调用同步并非易事。这样做将迫使您的用户在程序再次响应之前等待来自服务器的响应。除非您确定数据集很小且访问频率不是很高,否则您应该寻找其他方式。

【讨论】:

这绝对不是您应该追求的解决方案。我看不到您的屏幕截图,但很明显您在某处做错了,因为您几乎不是第一个使用 jQuery 异步调用方法的人(我今天早些时候确实这样做了)。其次,如果您要翻译网页,这可能不是您应该采用的方法。 如果您有更好的解决方案,请务必发布! 必须如此!!在另一个 Ajax 调用中存在一个 Ajax 调用。当异步执行时,它们都会混淆。内部需要同步。【参考方案4】:

我看不到你的截图(imgur 域被我屏蔽了)而且你没有发布很多代码,所以我将向你展示我是如何做到的,我可以更新答案以获得更好的答案稍后你的问题。

我调用了一个存储过程并使用 AJAX 将结果数据插入到我的页面中。

首先,我在 C# 中有一个包含开始和结束日期的对象。我的模型:

public class DateRange

    public DateTime? StartDate  get; set; 
    public DateTime? EndDate  get; set; 

我的数据访问层 (DateRepository),它调用我的存储过程(将其匿名化一点,因为它与这个问题无关):

public static List<DateRange> GetDates(int number)

    // execute stored procedure, ORM converts the rows to a list of objects
    ...
    return dateRanges;

我的服务层,调用数据访问层:

[Route("Dates/number")]
public IHttpActionResult Get_DateRanges(int number)

    var response = DateRepository.GetDates(number);
    return Json(response);

Json(result) 来自 System.Web.Http > ApiController > JsonResult&lt;T&gt; Json&lt;T&gt;(T content)

现在,我的 UI 层控制器调用此服务方法:

public async Task<JsonResult> Get_DateRanges(int number)

    var response = await ServiceClient.HttpGetList<DateRange>([url here calling /Dates/number ]);
    return new JsonResult  Data = response, MaxJsonLength = Convert.ToInt32(WebConfigurationManager.AppSettings["MaxJsonLength"]), JsonRequestBehavior = JsonRequestBehavior.AllowGet ;

还有ServiceClient 方法(简化,省略授权等细节):

public static class ServiceClient

    public static async Task<List<T>> HttpGetList<T>(string url)
    
        using (var client = SetupHttpClient())
        
            HttpResponseMessage response = await client.GetAsync(url);
            CheckResponse(response);

            var tList = await response.Content.ReadAsAsync<List<T>>();
            return tList;
        

    

记住,这个 JSONResult 是List&lt;DateRange&gt;。这就是 JSON 的数据字段中的内容。

最后是调用UI控制器方法的javascript代码:

function updateDateRanges() 
    var nNumber = $("input#Number").val();
    var params =  number: nNumber ;

    // note the JSON call is to the UI layer
    $.getJSON(ROOT + "UIController/Get_DateRanges", params, function (data)  )
    .done(function (data) 
        // change model values from server
        $("input#StartDate").val(data[0].StartDate);
        $("input#EndDate").val(data[0].EndDate);
    )
    .fail(function () 
        errorAlert("Error retrieving dates.");
    )



请注意,我检索日期的方式(例如 data[0].StartDate)是因为我有一个日期范围对象列表。由于您可以单独调用返回 JSON 的函数(就像我在浏览器中输入服务层的 URL 一样),应该很容易看到 JSON data 的样子。

通过查看您的 cmets,您的问题似乎根本不是原始帖子中所述,而是对 javascript 异步性质的基本了解。考虑以下示例:

$("#output").click(function() 
    var inputText = $("#output").text();
    translateWord(inputText);
);

function translateWord(word)
    getTranslationFromServer(word);


function getTranslationFromServer(word) 
    // using setTimeout to simulate slow response (2 seconds) instead of AJAX request
    setTimeout(function()
        $("#output").text("texto en español");
    , 2000);

    $("#output").css('background-color', 'yellow');

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="output">
English text
</div>

请注意,尽管首先调用了setTimeout 函数,但立即发生的是背景变为黄色,2 秒后,文本被翻译。这是由于 Javascript 的异步特性。在等待您的 AJAX 调用时,它已移至下一行。因此,在您的特定示例中,您设置var t = "";,进行AJAX 调用,下一行是return t;。因此,当您等待 AJAX 调用时,程序已移至下一行,即return:退出此函数并将此值返回给调用者。所以你在它有机会完成之前退出你的功能。

好的,所以你真正的问题是:“在返回另一个函数之前,我如何等待这个 javascript 函数完成?”好吧,我最初建议回调,但现在更好的解决方案是使用 Promise。既然你好像在用jQuery,我就用他们的promise library:

$("#output").click(function() 
    var inputText = $("#output").text();
    translateWord(inputText);
);

function translateWord(word)
    $("#output").text("waiting...");
    $.when(getTranslationFromServer(word))
	.then(
    	function(word) 
    		$("#output").text(word);
                $("#output").css('background-color', 'orange');
    	
  		
    );


function getTranslationFromServer(input) 
$("#output").css('background-color', 'yellow');
    var deferred = new $.Deferred();
    var output = "";
    // using setTimeout to simulate slow response (2 seconds) instead of AJAX request
    setTimeout(function()
        // mock translate function
        if (input === "English text") 
            output = "texto en español";
        
        else if (input === "texto en español") 
            output = "English text";
        
        else 
            output = "No translation for this text found."
        
        deferred.resolve(output);
        , 2000);

    return deferred.promise();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="output">English text</div>

我更改了背景颜色,希望能帮助您了解 javascript 在代码中的位置。我相信这最终回答了您关于 javascript 的 XY 问题。

【讨论】:

好的。您的解决方案就是我所说的“传统”,也是我们许多开发人员每天都这样做的方式。您的 $.getJSON 正在将值直接写入 DOM。但是正如您从问题中看到的(如果您能看到它),我想知道如何从可以在 Javascript 中调用的函数中获取 AJAX 调用的结果作为返回值。通过这种方式,该函数可以变得通用(如首字母大写)并根据需要在任何地方使用,而不仅仅是用于特定用例。为什么我需要这种方式?因为在这种情况下,我是从另一个 AJAX 函数内部调用它! @KeithHarris 我的方法超出了通用性——数据被插入到 DOM 中,因为我正在显示该数据。这并没有使任何事情变得不那么普遍。如果您需要从另一个异步函数内部调用异步函数,听起来您需要了解回调如何在 Javascript 中工作。 您的解决方案对我不起作用,因为我不提前知道运行时 DOM 会是什么。事实上,DOM 是根据允许用户访问的内容动态构建的。我意识到这是一个不寻常的案例(因为我以前从来没有这样做过)所以我想知道那里的其他开发人员是否有类似的问题以及他们是如何解决的。 我尝试使用回调函数(也显示在您看不到的屏幕截图中),但它也不起作用。 @KeithHarris 我已经用 sn-ps 回答了你的问题,展示了等待 AJAX 调用的正确方法,希望能帮助你理解 javascript。如果您能帮我一个大忙,那就是将您的实际代码编辑到您的原始问题中,因为您复制/粘贴它比我从手机上的屏幕截图中重新输入要容易得多.如果您希望我实际使用您的代码作为示例,您需要为我发布它。

以上是关于如何从 jQuery 调用 C# 静态方法的主要内容,如果未能解决你的问题,请参考以下文章

C#如何静态调用C++中的方法(静态调用dll)

我可以通过 COM 从 VBA 调用 C# 类的静态方法吗?

jquery---调用静态方法-each--map-数组与伪数组的差别

C#中静态方法和实例化方法的区别

单声道嵌入,从 C 调用 C# 泛型方法

C# 静态方法 静态属性 调用静态方法