接受List <customobject>的ASP.NET Web方法失败,“Web服务方法名称无效。”</customobject>

时间:2010-02-08 23:54:21

标签: asp.net jquery web-services asmx invalidoperationexception

我想创建一个接受自定义对象列表的Web方法(通过jQuery / JSON传入)。

当我在本地运行网站时,一切似乎都有效。 jQuery和ASP.NET,每个人都很高兴。但当我把它放在我们的一台服务器上时,它会爆炸。在ajax请求之后,jQuery收到500错误,响应为:

  

System.InvalidOperationException:EditCustomObjects Web Service方法名称无效。

这是网络服务方法:

[WebMethod]
public void EditCustomObjects(int ID, List<CustomObject> CustomObjectList)
{
  // Code here
}

我的jQuery代码(我认为不重要,因为错误似乎发生在Web服务级别上):

var data = JSON.stringify({
  ID: id,
  CustomObjectList: customObjectList
});

$.ajax({
  type: "POST",
  url: "/manageobjects.asmx/EditCustomObjects",
  data: data,
  contentType: "application/json; charset=utf-8",
  async: false,
  dataType: "json",
  success: function(xml, ajaxStatus) {
    // stuff here
  }
});

customObjectList初始化如下:

var customObjectList = [];

我像这样添加项目(通过循环):

var itemObject = { 
  ObjectTitle = objectTitle,
  ObjectDescription = objectDescription,
  ObjectValue = objectValue
}

customObjectList.push(itemObject);

所以,我在这里做错了吗?有没有更好的方法将数据数组从jQuery传递到ASP.NET Web服务方法?有没有办法解决“Web服务方法名称无效”。错误?

仅供参考,我在Windows Server 2003计算机上运行.NET 2.0,并从此站点获取了上述代码:http://elegantcode.com/2009/02/21/javascript-arrays-via-jquery-ajax-to-an-aspnet-webmethod/

编辑:有人要求提供更多关于网络服务的信息,我宁愿不提供整个课程,但这里有一点可能会有所帮助:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService] 
public class ManageObjects : Custom.Web.UI.Services.Service 
{
}

巴拉

10 个答案:

答案 0 :(得分:4)

我根据您可以直接在浏览器中访问网络服务的评论进行分组。

只是为了将自定义对象与配置隔离开来,您可以放置​​另一个服务,例如:

[WebMethod]
public static string GetServerTimeString()
{
    return "Current Server Time: " + DateTime.Now.ToString();
}

从客户端调用jQuery ajax调用。如果这样可行,那么它可能与您的对象有关,而不是在服务器端配置。否则,请继续查看服务器端配置跟踪。

编辑:一些示例代码:

[WebMethod(EnableSession = true)]
public Category[] GetCategoryList()
{
    return GetCategories();
}
private Category[] GetCategories()
{
     List<Category> category = new List<Category>();
     CategoryCollection matchingCategories = CategoryList.GetCategoryList();
     foreach (Category CategoryRow in matchingCategories)
    {
         category.Add(new Category(CategoryRow.CategoryId, CategoryRow.CategoryName));
    }
    return category.ToArray();
}

以下是我发布复杂数据类型JSON值的示例

[WebMethod]
 public static string SaveProcedureList(NewProcedureData procedureSaveData)
 {
          ...do stuff here with my object
 }

这实际上包含了两个对象数组......我的NewProcedureData类型是在一个类中定义的。

EDIT2:

以下是我在一个实例中处理复杂对象的方法:

function cptRow(cptCode, cptCodeText, rowIndex)
{
    this.cptCode = cptCode;
    this.cptCodeText = cptCodeText;
    this.modifierList = new Array();
//...more stuff here you get the idea
}
/* set up the save object */
function procedureSet()
{
    this.provider = $('select#providerSelect option:selected').val(); // currentPageDoctor;
    this.patientIdtdb = currentPatientIdtdb;// a javascript object (string)
//...more object build stuff.
    this.cptRows = Array();
    for (i = 0; i < currentRowCount; i++)
    {
        if ($('.cptIcdLinkRow').eq(i).find('.cptEntryArea').val() != watermarkText)
        {
            this.cptRows[i] = new cptRow($('.cptIcdLinkRow').eq(i).find('.cptCode').val(), $('.cptIcdLinkRow').eq(i).find('.cptEntryArea').val(), i);//this is a javscript function that handles the array object
        };
    };
};
//here is and example where I wrap up the object
    function SaveCurrentProcedures()
    {

        var currentSet = new procedureSet();
        var procedureData = ""; 
        var testData = { procedureSaveData: currentSet };
        procedureData = JSON.stringify(testData);

        SaveProceduresData(procedureData);
    };
    function SaveProceduresData(procedureSaveData)
    {
        $.ajax({
            type: "POST",
            contentType: "application/json; charset=utf-8",
            data: procedureSaveData,
the rest of the ajax call...
        });
    };

注意!重要信息procedureSaveData名称必须与客户端和服务器端完全匹配才能使其正常工作。 EDIT3:更多代码示例:

using System;
using System.Collections.Generic;
using System.Web;

namespace MyNamespace.NewProcedure.BL
{
    /// <summary>
    /// lists of objects, names must match the JavaScript names
    /// </summary>
    public class NewProcedureData
    {
        private string _patientId = "";
        private string _patientIdTdb = "";

        private List<CptRows> _cptRows = new List<CptRows>();

        public NewProcedureData()
        {
        }

        public string PatientIdTdb
        {
            get { return _patientIdTdb; }
            set { _patientIdTdb = value; }
        }
       public string PatientId
        {
            get { return _patientId; }
            set { _patientId = value; }
        }
        public List<CptRows> CptRows = new List<CptRows>();

}

--------
using System;
using System.Collections.Generic;
using System.Web;

namespace MyNamespace.NewProcedure.BL
{
    /// <summary>
    /// lists of objects, names must match the JavaScript names
    /// </summary>
    public class CptRows
    {
        private string _cptCode = "";
        private string _cptCodeText = "";

        public CptRows()
        {
        }

        public string CptCode
        {
            get { return _cptCode; }
            set { _cptCode = value; }
        }

        public string CptCodeText
        {
            get { return _cptCodeText; }
            set { _cptCodeText = value; }
        }
     }
}

希望这有帮助。

答案 1 :(得分:1)

由于错误提到了Web方法名称的问题,我怀疑这完全是由于WSDL如何生成并映射到Web服务的问题。我看到两个潜在的问题:

  1. ID是一个非常常见的名称,可能会被保留或可能导致冲突。尝试将其重命名为objectId(大写参数名称不是.NET的标准)
  2. WSDL没有泛型类型的概念。根据生成器,为List<CustomObject>CustomObject[]生成的类型名称可能与您的参数名称CustomObjectList冲突。请尝试重命名第二个参数customObjects
  3. 或许这里还有其他一些愚蠢的框架问题。无论如何,您应该将问题添加到.NET生成的WSDL中。您可以通过从Web服务器下载/manageobjects.asmx?WSDL来获取WSDL XML。

答案 2 :(得分:0)

您可能需要检查system.web部分中的webServices / protocols元素,并确保添加了HttpPost。通常,本地帖子默认启用为开发模式,但不支持远程,这是在服务器上部署服务时的情况......

<system.web>
 ...
 <webServices>
  <protocols>
   <add name="HttpPost" />
  </protocols>
 </webServices>
</system.web>

我会详细介绍here

答案 3 :(得分:0)

也许您使用jquery传递的路径不存在尝试使用FireBug查看响应。

答案 4 :(得分:0)

每当我遇到这些类型的错误(在本地但不在服务器上工作)时,我会启动IIS管理工具(或者你正在使用的任何工具)并检查一切是否完全相同。如果没有使它们相同,那么一次改变一件小事。

根据您的角色/组织,您可能无法以这种方式访问​​服务器,但通常这些错误会归结为您从未查看的选项卡上最奇怪的随机复选框。

这是一个很长的镜头,但不禁尝试。

答案 5 :(得分:0)

您是否已注册所需的httpHandler以允许标记为ScriptService的webservices?

<httpHandlers>
   <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</httpHandlers>

答案 6 :(得分:0)

这是javascript中的错误声明。

var itemObject = { 
  ObjectTitle = objectTitle,
  ObjectDescription = objectDescription,
  ObjectValue = objectValue
}

正确的对象初始化应该是:

var itemObject = { 
  ObjectTitle : objectTitle,
  ObjectDescription : objectDescription,
  ObjectValue : objectValue
};

还可以尝试从async: false的参数中临时删除$.ajax

答案 7 :(得分:0)

不得不说,我不是100%卖出我的答案是(全部)问题,但这将解决反序列化问题。 为您的特定对象添加一些细节。

在客户端:

function itemObject (objectTitle,  objectDescription ,objectValue )
{
    this.ObjectTitle  = objectTitle,;
    this.ObjectDescription  = objectDescription ;
    this.ObjectValue  = objectValue ;
}; 

//  4 objects in source-fix for your list
function objRow()
{
    this.myCode = myCode;
    this.myCodeText = myCodeText;
    this.customObjectList  = new Array();
    for (k = 0; k < 4; k++)
    {
        this.customObjectList [k] = new itemObject (sourceTitle[k],sourceDescription[k],sourceValue[k]);
    };
};
var myCode = "hicode1";
var  myCodeText = "hicodeText1";
$(function()
{
   function SaveCurrentObjects()
    {
         var currentSet = new objRow();
        var objectData = "";
        var testData = {objectSaveData : currentSet };
        objectData = JSON.stringify(testData);

        SaveObjectsData(objectData );
    };

    /* save the objects */
    function SaveObjectsData(objectSaveData)
    {
        $.ajax({
            type: "POST",
            contentType: "application/json; charset=utf-8",
            data: objectSaveData,
            dataFilter: function(data)
            {
                var msg;
                if (typeof (JSON) !== 'undefined' &&
                typeof (JSON.parse) === 'function')
                    msg = JSON.parse(data);
                else
                    msg = eval('(' + data + ')');
                if (msg.hasOwnProperty('d'))
                    return msg.d;
                else
                    return msg;
            },
            url: "/manageobjects.asmx/EditCustomObjects", 
            success: function(msg)
            {
               //do stuff
            },
            failure: function(msg)
            {
               //handlefail
            }
        });
    };

});

在服务器端,您将拥有:(客户代码中的“objectSaveData”的确切名称)。

[WebMethod]
public static string EditCustomObjects(ObjectData objectSaveData)
{
   // code to save your object
   return "saved objects";
}

创建一个ObjectData类,其中包含一个objectItem列表,类似于我的另一个匹配对象的示例(小心名称)。

注意:我安装了ASP.NET ajax扩展 - 在此示例中使用asp.net 2.0代码。

答案 8 :(得分:0)

好吧,这是一个对象,它只是测试了这个: ============================================ ASPX ===== =============================

        $("#btngeMethodCallWithAnObjectAsAParameter").click(function (event) {

            $.ajax({
                type: 'POST',
                url: 'Default.aspx/PageMethodCallWithAnObjectAsAParameter',
                data: '{"id":"' + '5' + '", "jSonAsset":' + JSON.stringify(new BuildJSonAsset()) + '}',
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function (msg) {
                    if (msg.d) {
                        alert(msg.d);
                    }
                },
                error: function () {
                    alert("Error! Try again...");
                }
            });

        });
    });


    function BuildJSonAsset() {
        this.AssetId = '100';
        this.ContentId = '200';
        this.AssetName = 'Asset1';
    }

=============================================== =========================

[WebMethod()]
public static string PageMethodCallWithAnObjectAsAParameter(int id, JSonAsset jSonAsset)
{
    return "Success!";
}

=============================================== =======================

这适用于单个对象,接下来我将尝试一个对象列表:)

答案 9 :(得分:0)

确保您拥有此课程的顶部

[ScriptService] <--- this bit :D

public class Surveyors : WebService

同时检查你所有的parathesis,resharper对我有点疯狂,需要一段时间才能检查。

此外,如果您有许多webmethods,请尝试创建一个基本的hello world webservice,确保它实际上在第一时间工作,然后您可以从那里进行故障排除。

祝你好运。