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

时间:2013-12-29 10:26:30

标签: javascript jquery asp.net ajax pagemethods

我的.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);
}

现在我想通过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>

我的.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
 }

我的界面:

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; }

    }

8 个答案:

答案 0 :(得分:6)

基于聊天讨论的答案编辑

首先,谢谢你澄清你的问题。有点难以理解你试图解决的问题。原因?因为您的代码不够清晰,并且通常在存在设计问题时发生。这实际上是你面临的一个设计问题。首先,我会指出一些错误......

在这个javascript函数中......

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

this不是您网页的实例。所以没有必要让你的页面实现一个接口...

public partial class AppMaster : Log, IInfo{}

并期望javascript调用会将System.Web.UI.Page的实例分页到您的类(更不用说IInfo接口的实现)。你可以盲目地抛弃这种方法,因为这是一个永久性的设计问题,甚至都无法发挥作用。

现在,如果你想要的是服务页面,那么做一些进一步的处理,最后使用javascript / ajax异步地将这个处理的结果发送回客户端你有几种方法:

  1. 使用SignalR这是我最喜欢的方法(但您已说明您的解决方案不符合使用SignalR的要求)
  2. 使用jQuery ajax,这也是一种非常有效的方法
  3. 现在,我将解释第二种方法

    使用jQuery Ajax

    只需像在ASP.NET中一样呈现页面。然后在客户端,当页面加载时,发出ajax请求以开始处理您要显示的信息。您可以在页面加载后立即启动请求以在服务器上进行处理

    $(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
                }
        });
    });
    

    在成功处理程序中,您需要在Web控件上加载从ajax调用接收的值。然后将IInfo接口更改为单独代码文件中的具体对象。但是,请记住,此类不应该对您的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; }
    
    }
    

    然后将您的页面方法更改为...

    [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;
    }
    

    请注意,您需要从emp_num获取Session值,因为您在聊天讨论中声明此值来自Session变量。现在,返回到jQuery ajax调用的成功处理程序,该调用在从服务器收到响应后立即执行。您将在处理程序参数d中收到一个json对象,其中包含您刚刚从服务器发送的JSInfo类的属性。然后在页面上设置控件......

    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
            },
    

    这应该是一个更简洁的解决方案。在这里,我无法涵盖每一个细节。但肯定你会明白这个想法。如果没有,请告诉我是否需要扩展某些内容。

答案 1 :(得分:5)

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);
    }

}

抱歉,如果它不起作用

答案 2 :(得分:3)

如果您的页面实现了界面,则不必传递它!在你的c#代码中写:

this.l_power=true;

如果需要将值从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";
}

<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>

其中successfail是在请求完成后将调用的两个JS函数的名称。请注意,页面方法可以返回字符串值,以通知客户端服务器上发生了什么。

答案 3 :(得分:2)

我只能想到一种方法。

您应该以某种方式封送this对象,并将其作为参数发送。我的意思是你应该编写一个方法,将一个对象编组为等效的json或xml,并将POST编组到你的服务器上。

我相信你可以像上面那样只通过C#和javascript之间的干净API和编译工具来实现RPC,就像为GWT编写java一样和javascript。

答案 4 :(得分:2)

你能做一点测试吗?

在您的页面代码中声明public class JSInfo: IInfo{},并在您的Web方法中将您的参数声明为JSInfo。

当JSInfo实现IInfo时,您的程序逻辑可以毫无问题地使用它。

只是为了让您知道,您的代码无法正常工作,因为您无法将接口序列化 不是具体的类型,如果你考虑一下,接口在XML模式中没有真正的相关性。没有办法表示数据。然而,基类将起作用。

如果你在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);
     }
}

JSInfo只是给你的IInfo接口一些结构,因此可以序列化。

从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>

不是说你的页面顶部应该有一个ScriptManager

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

ScriptManager负责为您提供JavaScript中的PageMethods类 与其他事情。

另外,请确认以下内容:

  • 页面方法必须具有System.Web.Services.WebMethod属性。 [的WebMethod]
  • 页面方法必须是公开的。 [WebMethod] public ...
  • 页面方法必须是静态的。 [WebMethod] public static ...
  • 页面方法必须在页面上定义(内联或代码隐藏)。它无法在控件,母版页或基页中定义。
  • ASP.NET AJAX脚本管理器必须将EnablePageMethods设置为true。

答案 5 :(得分:2)

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);
}
}

然后

<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);

提到@anotherdie。并告诉你如何转移“X”

答案 6 :(得分:2)

在你的.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);
            });
}

在你的apsx.cs中(你可以返回一个字符串,一个列表,一个bool,一个int或一个json对象//为json使用json.net http://james.newtonking.com/json)为此我将返回一个bool。

using System.Web.Services;

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

在接口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;
   }

答案 7 :(得分:0)

我执行以下操作:

创建新页面并调用它: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 + "~";

        }

并在我的主页中:

 <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>