简体   繁体   English

如何在javascript事件中通过参数调用页面方法?

[英]How to call page method with a parameter through in a javascript event?

I have method like this in my .cs : 我的.cs中有这样的方法:

[System.Web.Services.WebMethod]
public static void GetServiceInformation(IInfo x) //IInfo  is an interface
{
    x.l_power = true;
    x.lb_InboxCount = UserTrans.GetInbox(int.Parse(emp_num), 0);
}

Now i want to call this method through a javascript method as a page method but it doesn't work . 现在我想通过javascript方法调用此方法作为页面方法,但它不起作用。

<script type ="text/javascript">

    function GetInfo() {
        PageMethods.GetServiceInformation(this);
    }
   window.onload = setTimeout("GetInfo()", 3000);
</script>

  <telerik:RadScriptManager ID="RadScriptManager1" runat="server" EnablePageMethods="true">
  </telerik:RadScriptManager>

My .cs : 我的.cs:

 public partial class AppMaster : Log, IInfo //My page
    {
        public string Inbox
        {
            get
            {
                return hpl_Inbox.NavigateUrl;
            }

            set
            {
                hpl_Inbox.NavigateUrl = value;
            }
        }
        public string Draft
        {
            get
            {
                return hpl_Draft.NavigateUrl;
            }

            set
            {
                hpl_Draft.NavigateUrl = value;
            }
        }

        public string New
        {
            get
            {
                return hpl_New.NavigateUrl;
            }
            set
            {
                hpl_New.NavigateUrl = value;
            }
        }
        public string Approved
        {
            get
            {
                return hpl_Approved.NavigateUrl;
            }
            set
            {
                hpl_Approved.NavigateUrl = value;
            }
        }
    //------- etc
 }

My interface : 我的界面:

public interface IInfo
    {
        string Inbox { get; set; }
        string Draft { get; set; }
        string New { get; set; }
        string Approved { get; set; }
        string archive { get; set; }
        string search { get; set; }
        string cand { get; set; }
        string pri { get; set; }
        string power { get; set; }
        string admin { get; set; }
        string help { get; set; }
        bool l_cand { get; set; }
        bool l_pri { get; set; }
        bool l_power { get; set; }
        bool l_admin { get; set; }

        string lb_ApprovedCount { get; set; }
        string lb_InboxCount { get; set; }
        string lb_archive { get; set; }
        string lb_DraftCount { get; set; }

    }

Answer Edit Based On Chat Discussion 根据聊天讨论回答编辑

First, thanks for clarifying your question. 首先,感谢您澄清您的问题。 It was bit hard to understand the problem you were trying to solve. 有点难以理解你试图解决的问题。 The reason? 原因? Because your code wasn't clear enough and that usually happens when there are design issues. 因为您的代码不够清晰,并且通常在存在设计问题时发生。 That's effectively what your facing here a bit of a design issue. 这实际上是你面临的一个设计问题。 First, I'll point out some mistakes... 首先,我会指出一些错误......

In this javascript function... 在这个javascript函数中......

function GetInfo() {
        PageMethods.GetServiceInformation(this);
    }

this is NOT an instance of your page. this不是您网页的实例。 So there's no use to make your page implement an interface... 所以没有必要让你的页面实现一个接口......

public partial class AppMaster : Log, IInfo{}

and expect that a javascript call would page an instance of System.Web.UI.Page to your class (not to mention an implementation of the IInfo interface). 并期望javascript调用将System.Web.UI.Page的实例分页到您的类(更不用说IInfo接口的实现)。 You can blindly ditch this approach because it's a permanent design issue and it's not even going to work. 你可以盲目地抛弃这种方法,因为它是一个永久性的设计问题,甚至都无法发挥作用。

Now, if what you want is to serve the page, then do some further processing and finally send the results of this processing back to the client asynchronously using javascript/ajax you have a couple of approaches here: 现在,如果你想要的是服务页面,那么做一些进一步的处理,最后使用javascript / ajax异步地将这个处理的结果发送回客户端你有几种方法:

  1. Using SignalR which is my favourite approach (but you already stated your solution doesn't meet the requirements to use SignalR ) 使用SignalR这是我最喜欢的方法(但你已经声明你的解决方案不符合使用SignalR的要求)
  2. Using jQuery ajax which is also a very valid approach 使用jQuery ajax这也是一种非常有效的方法

Now, I'll explain the second approach 现在,我将解释第二种方法

Using jQuery Ajax 使用jQuery Ajax

Simply render the page as you would normally do in ASP.NET . 只需像在ASP.NET通常那样呈现页面。 Then on the client-side, when the page loads, make an ajax request to start processing the information you want to display. 然后在客户端,当页面加载时,发出ajax请求以开始处理您要显示的信息。 You can start the request as soon as the page loads to make the processing on the server 您可以在页面加载后立即启动请求以在服务器上进行处理

$(function(){
    $.ajax({
        type: 'POST',
        url: 'AppMaster.aspx/GetServiceInformation',
        data: "{}",
        contentType: 'application/json;charset=utf-8',
        dataType: 'json',
        success: function(d) {
            //load data received
            },
        error: function() {
            //process the error
            }
    });
});

In the success handler you need to load the values received from the ajax call on your web controls. 在成功处理程序中,您需要在Web控件上加载从ajax调用接收的值。 Then change your IInfo interface to a concrete object in a separate code file. 然后将IInfo接口更改为单独代码文件中的具体对象。 But, remember that this class should NOT hold any references whatsoever to your web controls 但是,请记住,此类不应对您的Web控件进行任何引用

public class JSInfo
{
    string Inbox { get; set; }
    string Draft { get; set; }
    string New { get; set; }
    string Approved { get; set; }
    string archive { get; set; }
    string search { get; set; }
    string cand { get; set; }
    string pri { get; set; }
    string power { get; set; }
    string admin { get; set; }
    string help { get; set; }
    bool l_cand { get; set; }
    bool l_pri { get; set; }
    bool l_power { get; set; }
    bool l_admin { get; set; }

    string lb_ApprovedCount { get; set; }
    string lb_InboxCount { get; set; }
    string lb_archive { get; set; }
    string lb_DraftCount { get; set; }

}

then change your page method to... 然后将您的页面方法更改为...

[System.Web.Services.WebMethod]
public static JSInfo GetServiceInformation()
{
    //you need to get the emp_num from session

    //construct the JSInfo object
    JSInfo info = new JSInfo();

    //get the data from the database
    var data = UserTrans.GetInbox(int.Parse(emp_num), 0);

    //set the properties of the JSInfo...similar to the line below for each property...Draft, New, Approved, etc
    info.Inbox = data.Inbox;

    //return the object to the client
    return info;
}

Notice that you need to get the emp_num value from Session since you stated in the chat discussion that this value comes from a Session variable. 请注意,您需要从Session获取emp_num值,因为您在聊天讨论中声明此值来自Session变量。 Now, going back to the success handler of your jQuery ajax call which executes soon after the response is received back from the server. 现在,返回到jQuery ajax调用的成功处理程序,该调用在从服务器收到响应后立即执行。 You will receive a json object in the handler parameter d with the properties of the JSInfo class that you just sent from the server. 您将在handler参数d收到一个json对象,其中包含您刚刚从服务器发送的JSInfo类的属性。 Then you set the controls on the page... 然后你在页面上设置控件......

success: function(d) {
            $('#id_inbox_control').val(d.Inbox);
            $('#id_draft_control').val(d.Draft);
            $('#id_new_control').val(d.New);

            //and keep doing the same for the rest of the controls
        },

That should be a neater solution. 这应该是一个更简洁的解决方案。 Of coure, I cannot cover every single details here. 在这里,我无法涵盖每一个细节。 But for sure you will get the idea. 但肯定你会明白这个想法。 If not, let me know if I need to expand on something. 如果没有,请告诉我是否需要扩展某些内容。

function GetServiceInformation(x) {

    $.ajax({
        type: "POST",
        url: "page.aspx/GetServiceInformation",
        data: "{'x':'" + x + "'}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: on_sucess,
        error: on_error
    });
    function on_sucess(data, status) {

        alert(data);

    }
    function on_error(request, status, error) {

        alert(error);
    }

}

Sorry, if it doesn't work 对不起,如果它不起作用

If your page implements the interface, you don't have to pass it! 如果您的页面实现了界面,则不必传递它! In your c# code write: 在你的c#代码中写道:

this.l_power=true;

If you need to pass values from JavaScript to page method, define each property as a parameter and pass values to the page method: 如果需要将值从JavaScript传递给页面方法,请将每个属性定义为参数并将值传递给页面方法:

[System.Web.Services.WebMethod]
public static string GetServiceInformation(int value1, string value2)
{
    l_power = value1;
    something = value2;
    return "some string to indicate the result of call";
}

And: 和:

<script type ="text/javascript">
    var v1 = 15;
    var v2 = "some value";
    function GetInfo() {
        PageMethods.GetServiceInformation(v1, v2, success, fail);
    }
   window.onload = setTimeout("GetInfo()", 3000);
</script>

in which success and fail are the names of two JS functions that will be called after the request is completed. 其中successfail是在请求完成后将调用的两个JS函数的名称。 Note that a page method can return a string value to inform the client about what happened on the server. 请注意,页面方法可以返回字符串值,以通知客户端服务器上发生的情况。

I can only think of one method. 我只能想到一种方法。

You should somehow marshal the this object, and send it as parameter. 您应该以某种方式封送this对象,并将其作为参数发送。 I mean you should write a method that marshalls an object to equivalent json or xml, and POST that to your server. 我的意思是你应该写的是马绍尔群岛一个目标是等效的JSON或XML和方法POST ,为您的服务器。

I believe you can do it as you did above only through a clean API and compiler tool between C# and javascript to implement RPC just like GWT was written for java and javascript. 我相信你可以像上面那样只通过C#和javascript之间的干净API和编译工具实现RPC ,就像为java和javascript编写GWT一样。

Can you do a little test? 你能做一点测试吗?

Declare a public class JSInfo: IInfo{} in your page code, and in your web method declare that parameter of yours as JSInfo. 在您的页面代码中声明一个public class JSInfo: IInfo{} ,并在您的Web方法中将您的参数声明为JSInfo。

As JSInfo implements IInfo, your program logic can work with it without any problem. 当JSInfo实现IInfo时,您的程序逻辑可以毫无问题地使用它。

Just to let you know, your code does not work because you cannot serialize interfaces as they are not concrete types, if you think about it, interfaces have no real correlation in XML schema. 只是为了让您知道,您的代码不起作用,因为您不能序列化接口,因为它们不是具体类型,如果您考虑它,接口在XML模式中没有真正的相关性。 There's no way to represent the data. 没有办法表示数据。 Base classes will work however. 然而,基类将起作用。

If you fill bad in declaring the JSInfo in the asp.net page class, then create a class called WebMethodsHelper and declare your JavaScript WebMethod Interfaces (Adaptors) there. 如果你在asp.net页面类中声明JSInfo时填写不好,那么创建一个名为WebMethodsHelper的类并在那里声明你的JavaScript WebMethod接口(适配器)。

public class JSInfo: IInfo{
    private ControlsCollection controls;

    public JSInfo(ControlsCollection constrols){
        this.controls = controls
        FillObjects();
    }

    private void FillObjects(){
        //iterate through controls and extract you data to you 
        //class properties/fields
    }

    public void Update(ControlsCollection controls){
        this.controls=controls;
        FillObjects();
    }

    public void Update(JSInfo info, ControlsCollection controls){
        this.controls=controls;

        //populate your object based on info

        //then extract data from page controls
        FillObjects();
    }
}


public class MyPage: System.Web.UI.Page{

     protected void Page_Load(object sender, EventArgs e){
          if(!IsPostBack && Session["info_obj"])
               Session["info_obj"] = new JSInfo(this.Controls);
     }

     [System.Web.Services.WebMethod]
     public static string GetServiceInformation(JSInfo data)
     {
         JSInfo info = new JSInfo(this.Controls);
         info.Update(data);

         //or if you stored the info in the session
         JSInfo info = (JSInfo)Session["info_obj"];
         info.Update(this.Controls, data);
     }
}

The JSInfo is just to give your IInfo interface some structure so it can be serialized. JSInfo只是给你的IInfo接口一些结构,所以它可以被序列化。

From JavaScript you should be able to call you page method like this: 从JavaScript你应该可以这样称呼你的页面方法:

<script type ="text/javascript"> 

function GetInfo() { 
     var info = new JSInfo();
     info.PropertyXPTO="something";

     PageMethods.GetServiceInformation(info, onSuccess, onError);
} 

function onSuccess(result) {
    alert(result);
}

function onError(result) {
    alert('error: ' + result);
}

window.addEventListener("load", function(){
   setTimeout("GetInfo()", 10 * 1000); 
}, false);

</script>

Not that you should have a ScriptManager at the top of your page 并不是说你的页面顶部应该有一个ScriptManager

<asp:ScriptManager ID="ScriptManager1" EnablePageMethods="true" runat="server" />

The ScriptManager is responsible for giving you the PageMethods class in the JavaScript, along with other things. ScriptManager负责为您提供JavaScript中的PageMethods类以及其他内容。

Also, confirm the following: 另外,请确认以下内容:

  • The page method must have the System.Web.Services.WebMethod attribute. 页面方法必须具有System.Web.Services.WebMethod属性。 [WebMethod] [的WebMethod]
  • The page method must be public. 页面方法必须是公共的。 [WebMethod] public ... [WebMethod]公开......
  • The page method must be static. 页面方法必须是静态的。 [WebMethod] public static ... [WebMethod]公共静态...
  • The page method must be defined on the page (either inline or in the code-behind). 页面方法必须在页面上定义(内联或代码隐藏)。 It cannot be defined in a control, master page, or base page. 它无法在控件,母版页或基页中定义。
  • The ASP.NET AJAX Script Manager must have EnablePageMethods set to true. ASP.NET AJAX脚本管理器必须将EnablePageMethods设置为true。
function GetServiceInformation(x) {
$.ajax({
    type: "POST",
    url: "page.aspx/GetServiceInformation",
    data:  x, //Attention: there is no {}
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: on_sucess,
    error: on_error
});
function on_sucess(data, status) {
    alert(data);
}
function on_error(request, status, error) {
    alert(error);
}
}

And then 然后

<script type ="text/javascript">

function GetInfo() {
var myInfo = {
        Inbox: "",
        Draft: "",
        New: "",
        l_cand: ""
        ......//Attention, you should make this class corresponding to your server class IInfo
    };
    PageMethods.GetServiceInformation(myInfo);
}
window.onload = setTimeout("GetInfo()", 3000);

Referred to @anotherdie. 提到@anotherdie。 And tell you how to transfer "X" 并告诉你如何转移“X”

In your .js 在你的.js

function GetInfo() { 
    var parameter = {};
    parameter.name = "test";
    parameter.id = 123;
    parameter.state = true;

    PageMethods.GetServiceInformation(parameter, 
            function (res) {
                if (res == true) {
                     //do some
                     alert("ok");
                   } else {
                     //do some
                     alert("bad");       
                   }
            }, function(err){
               alert("ERROR: "+err._message);
            });
}

in your apsx.cs (you can return a string, a list, a bool, an int or a json object //for json use json.net http://james.newtonking.com/json ) for this i'll return a bool. 在你的apsx.cs中(你可以返回一个字符串,一个列表,一个bool,一个int或一个json对象//为json使用json.net http://james.newtonking.com/json )这个我会返回一个博尔。

using System.Web.Services;

[WebMethod]
public static bool GetServiceInformation(ClassData parameters)
{
  try
  {
    //do some
    return true;
  }    
  catch(Exception ex)
  {
     return false;
  }
}

in a interface ClassData .cs 在接口ClassData .cs中

   public string name { get; set; }
   public int id { get; set; }
   public bool state { get; set; }

   public ClassData(){}

   public ClassData(string _name, int _id, bool _state)
   {
     this.name = _name;
     this.id= _id;
     this.state = _state;
   }

I do the following : 我做以下事情:

Create New Page and called it : Counts.aspx 创建新页面并调用它: Counts.aspx

 protected void Page_Load(object sender, EventArgs e)
        {

                        emp_num = int.Parse(Session["empnum"].ToString());
                        Thread.Sleep(3000);
                        string res = GetCounts(emp_num);
                        Response.Write(res);

        }
        /***********************************************************************************************/
        protected string GetCounts(int empNum)
        {

            string outbox = UserTransaction.getoutboxCount(empNum, 0);
            string inbox = UserTransaction.getinboxCount(empNum, 0);
            string archive = UserTransaction.getarchivecount(empNum, 0);
            string draft = UserTransaction.getdraftcount(empNum, 0);
            return outbox + "~" + inbox + "~" + archive + "~" + draft + "~";

        }

and in my main page : 在我的主页中:

 <script type="text/javascript">

        function loadXMLDoc() {
            var xmlhttp;
            if (window.XMLHttpRequest) {
                xmlhttp = new XMLHttpRequest();
            }
            else {
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
            xmlhttp.onreadystatechange = function() {
                if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                    var split = xmlhttp.responseText.split('~');

                    var outbox = split[0];
                    var inbox = split[1];
                    var archive = split[2];
                    var draft = split[3];
                    document.getElementById("lbl_DraftCount").innerHTML = draft;
                    document.getElementById("lbl_InboxCount").innerHTML = inbox;
                    document.getElementById("lbl_ApprovedCount").innerHTML = outbox;
                    document.getElementById("lbl_archive").innerHTML = archive;
                }
            }
            xmlhttp.open("GET", "Counts.aspx", true);
            xmlhttp.send();
        }
        loadXMLDoc();


    </script>

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

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