使用Jquery调用异步WebMethod的ASP.NET

3

我正在尝试创建一个ASP应用程序,可以在其中编写出发地和目的地城市。我想在此文本框上实现Google自动完成。

我已经开发了一个异步方法,当您插入一个或多个字母时返回Google的自动完成函数,名为“getAutoComplete”。

现在我想通过Ajax请求从我的JavaScript中访问它。

以下是我的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成功函数中获取我的方法的结果。目的是不使用回调函数获得结果。

谢谢


嗨,这是一个旧的线程,但我想帮助那些至少来寻求那种用法的人。您会收到500(内部服务器错误)是因为该方法的访问修饰符被定义为 private。如果您想要从外部访问,您应该将访问修饰符更改为 public - Abdurrahman I.
1个回答

1

好的,我已经想出了如何解决这个问题。为了通过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 中。
    [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,并获得正确的响应。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接