繁体   English   中英

asp.net用Jquery调用异步webMethod

[英]asp.net call asynchronous webMethod with Jquery

我正在尝试创建一个asp应用程序,在那里我可以编写出发地和目的地城市。 我想在此文本框中实现Google AutoComplete。

我开发了异步方法,当你插入一个名为'getAutoComplete'的字母时,会返回google的自动完成功能。

现在我想从我的javascript访问它,带有ajax请求。

这是我的aspx代码

<%@ Page Async="true" Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="googleApiWeb._Default" %>
<asp:Content runat="server" ID="BodyContent" ContentPlaceHolderID="MainContent">
<ol class="round">

    <div id="DEPARTURE_CITY" style="margin-top: 15px; margin-left: 15px;">
        <asp:Label ID="lblDepartureCity" runat="server" Text="Ville de départ"></asp:Label>
        <asp:TextBox runat="server" ID="txbDepartureCity" ClientIDMode="Static" Style="width: 150px;"></asp:TextBox>
    </div>
    <div id="DESTINATION_CITY" style="margin-top: 15px; margin-left: 15px;">
        <asp:Label ID="lblDestinationCity" runat="server" Text="Ville d'arrivé"></asp:Label>
        <asp:TextBox runat="server" ID="txbDestinationCity" ClientIDMode="Static" Style="width: 150px;"></asp:TextBox>
    </div>
    <asp:Button ID="buttonValider" runat="server" Text="Valider" ClientIDMode="Static" OnClick="buttonValider_Click" />
    <asp:Label ID="lbl1" runat="server" Text=""></asp:Label>
    <asp:Label ID="lbl2" runat="server" Text=""></asp:Label>
</ol>
<script type="text/javascript">
    $(document).ready(function () {
        //Autocomplete
        $("#txbDepartureCity").bind("change paste keyup", function () {
            $.ajax({
                type: "POST",
                url: "/Default.aspx/getAutoComplete",
                data: "{'Element':'" + $(this).val() + "'}",
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function (response) {
                    alert(response.d);
                }
            });
        });

        $("#txbDestinationCity").bind("change paste keyup", function () {
            $.ajax({
                type: "POST",
                url: "/Default/googleAutoComplete",
                data: "{'Element':'" + $(this).val() + "'}",
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function (response) {
                    if (response.d == "NOK") {
                        //errorResponseAlert();
                    }
                }
            });


        });
    });
</script>

现在我的代码背后

namespace googleApiWeb
{
public partial class _Default : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    #region WebMethod autocomplete GoogleApi

    [WebMethod(EnableSession = true)]
    public static string googleAutoComplete(string Element)
    {
        string x = getAutoComplete(Element);

        return "";
    }

    [WebMethod(EnableSession = true)]
    private static async Task<string> getAutoComplete(string Element)
    {
        // Adresse à compléter
        string location = Element;

        // Message d'erreur s'il y en a
        string error = "";

        // Créer une instance d'auto complete
        AutoComplete autoComplete = new AutoComplete();

        // Options de l'auto complete
        AutoCompleteOptions options = new AutoCompleteOptions()
        {
            // Obtenir les résultats en français
            Language = LanguageEnum.French,

            // Pays dans lequel vous souhaitez limiter vos résultats
            // Attention : format ISO 3166-1 : "us", "fr", "de", ...
            CountryFilter = "fr",

            // Type de résultats à retourner.
            // Ex : Regions retourne le code postal, ce que ne fait pas Cities.
            // Si cette option est vide, tous les résultats sont retournés.
            TypeFilter = TypeFilterEnum.Regions
        };

        // Clé API
        string key = "XXXXXXX";

        // Appel asynchrone de la méthode de la dll

        var listOfLocation = await autoComplete.GetAutoComplete(location, key, null).ContinueWith(t =>
        {
            // S'il y a une erreur
            if (t.IsFaulted)
            {
                // Message de l'exception
                error = t.Exception.InnerException.Message;

                return null;
            }

            // Résultat
            return t.Result;
        });

        var result = listOfLocation.First();

        return result;
    }

    #endregion

    protected void buttonValider_Click(object sender, EventArgs e)
    {
        GetTrip();
        getAutoComplete(txbDepartureCity.Text);
    }
}
}

并且错误是POST http://localhost:51460/Default.aspx/getAutoComplete 500 (Internal Server Error)

我如何管理这个,以便在我的方法的结果上获得ajax成功函数。 这样做的目的是获得没有回调的结果。

谢谢

好的,所以我想出了如何解决这个问题。 为了在ajax中调用web方法,web方法必须返回一个字符串。 所以这个方法不能是异步的。

我在我的代码后面添加了这个类

public static class AsyncHelpers
{
    /// <summary>
    /// Execute's an async Task<T> method which has a void return value synchronously
    /// </summary>
    /// <param name="task">Task<T> method to execute</param>
    public static void RunSync(Func<Task> task)
    {
        var oldContext = SynchronizationContext.Current;
        var synch = new ExclusiveSynchronizationContext();
        SynchronizationContext.SetSynchronizationContext(synch);
        synch.Post(async _ =>
        {
            try
            {
                await task();
            }
            catch (Exception e)
            {
                synch.InnerException = e;
                throw;
            }
            finally
            {
                synch.EndMessageLoop();
            }
        }, null);
        synch.BeginMessageLoop();

        SynchronizationContext.SetSynchronizationContext(oldContext);
    }

    /// <summary>
    /// Execute's an async Task<T> method which has a T return type synchronously
    /// </summary>
    /// <typeparam name="T">Return Type</typeparam>
    /// <param name="task">Task<T> method to execute</param>
    /// <returns></returns>
    public static T RunSync<T>(Func<Task<T>> task)
    {
        var oldContext = SynchronizationContext.Current;
        var synch = new ExclusiveSynchronizationContext();
        SynchronizationContext.SetSynchronizationContext(synch);
        T ret = default(T);
        synch.Post(async _ =>
        {
            try
            {
                ret = await task();
            }
            catch (Exception e)
            {
                synch.InnerException = e;
                throw;
            }
            finally
            {
                synch.EndMessageLoop();
            }
        }, null);
        synch.BeginMessageLoop();
        SynchronizationContext.SetSynchronizationContext(oldContext);
        return ret;
    }

    private class ExclusiveSynchronizationContext : SynchronizationContext
    {
        private bool done;
        public Exception InnerException { get; set; }
        readonly AutoResetEvent workItemsWaiting = new AutoResetEvent(false);
        readonly Queue<Tuple<SendOrPostCallback, object>> items =
            new Queue<Tuple<SendOrPostCallback, object>>();

        public override void Send(SendOrPostCallback d, object state)
        {
            throw new NotSupportedException("We cannot send to our same thread");
        }

        public override void Post(SendOrPostCallback d, object state)
        {
            lock (items)
            {
                items.Enqueue(Tuple.Create(d, state));
            }
            workItemsWaiting.Set();
        }

        public void EndMessageLoop()
        {
            Post(_ => done = true, null);
        }

        public void BeginMessageLoop()
        {
            while (!done)
            {
                Tuple<SendOrPostCallback, object> task = null;
                lock (items)
                {
                    if (items.Count > 0)
                    {
                        task = items.Dequeue();
                    }
                }
                if (task != null)
                {
                    task.Item1(task.Item2);
                    if (InnerException != null) // the method threw an exeption
                    {
                        throw new AggregateException("AsyncHelpers.Run method threw an exception.", InnerException);
                    }
                }
                else
                {
                    workItemsWaiting.WaitOne();
                }
            }
        }

        public override SynchronizationContext CreateCopy()
        {
            return this;
        }
    }

现在在我的网络方法中

    [WebMethod(EnableSession = true)]
    public static string googleAutoComplete(string Element)
    {
        string result = "";

        List<string> lstReturnGoogle = AsyncHelpers.RunSync<List<string>>(() => getAutoComplete(Element));
        if (lstReturnGoogle != null)
        {
            result = "[";

            foreach (string t in lstReturnGoogle)
            {
                result += '"' + t + '"' + ',';
            }
            result = result.Remove(result.Length - 1, 1);
            result += "]";
            result.Replace('\\', ' ');
        }

        return result;
    }

有了这个,我可以在ajax中调用我的Webmethod,并得到正确的响应。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM