El método web de ASP.NET que acepta una lista está fallando con “El nombre del método de servicio web no es válido”.

Quiero crear un método web que acepte una lista de objetos personalizados (que se pasa a través de jQuery / JSON).

Cuando ejecuto el sitio web localmente, todo parece funcionar. jQuery y ASP.NET y todos están felices. Pero cuando lo pongo en uno de nuestros servidores, explota. jQuery recibe un error 500 después de la solicitud de ajax con la respuesta que es:

System.InvalidOperationException: el nombre del método del servicio web EditCustomObjects no es válido.

Aquí está el método de servicio web:

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

Y mi código jQuery (que no creo que importe, ya que el error parece estar ocurriendo en el nivel de servicio 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 } }); 

El customObjectList se inicializa así:

 var customObjectList = []; 

Y le agrego elementos así (a través de un bucle):

 var itemObject = { ObjectTitle = objectTitle, ObjectDescription = objectDescription, ObjectValue = objectValue } customObjectList.push(itemObject); 

Entonces, ¿estoy haciendo algo mal aquí? ¿Hay una mejor manera de pasar una matriz de datos de jQuery a un método de servicio web ASP.NET? ¿Hay una manera de resolver el “nombre del método de servicio web no es válido” ¿error?

Para su información, estoy ejecutando .NET 2.0 en una máquina con Windows Server 2003, y obtuve el código para lo anterior en este sitio: http://elegantcode.com/2009/02/21/javascript-arrays-via-jquery-ajax -en-an-aspnet-webmethod /

EDITAR: Alguien solicitó más información sobre el servicio web, prefiero no proporcionar toda la clase, pero aquí hay un poco más que puede ayudar:

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

Bara

Realizo la confirmación en función de los comentarios a los que puede ir directamente al servicio web en el navegador.

Solo para aislar su objeto personalizado de la configuración, puede colocar otro servicio como:

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

Llamar a eso desde un lado del cliente jQuery ajax call. Si esto funciona, entonces probablemente esté relacionado con su objeto específicamente y no con la configuración en el lado del servidor. De lo contrario, siga buscando en la pista de configuración del lado del servidor.

EDIT: Algunos ejemplos de código:

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

Y aquí hay un ejemplo de donde publico un tipo de datos complejo valor JSON

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

Esto incluye dos matrices de objetos dentro de él … mi tipo NewProcedureData está definido en una clase que los establece.

EDIT2:

Aquí es cómo manejo un objeto complejo en una instancia:

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

NOTA: IMPORTANTE, el nombre de ProcedureSaveData debe coincidir exactamente en el lado del cliente y del servidor para que esto funcione correctamente. EDIT3: más ejemplo de código:

 using System; using System.Collections.Generic; using System.Web; namespace MyNamespace.NewProcedure.BL { ///  /// lists of objects, names must match the JavaScript names ///  public class NewProcedureData { private string _patientId = ""; private string _patientIdTdb = ""; private List _cptRows = new List(); public NewProcedureData() { } public string PatientIdTdb { get { return _patientIdTdb; } set { _patientIdTdb = value; } } public string PatientId { get { return _patientId; } set { _patientId = value; } } public List CptRows = new List(); } -------- using System; using System.Collections.Generic; using System.Web; namespace MyNamespace.NewProcedure.BL { ///  /// lists of objects, names must match the JavaScript names ///  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; } } } } 

Espero que esto ayude.

Dado que el error menciona un problema con el nombre del método web, sospecho que esto se debe en su totalidad a problemas en la forma en que se genera el WSDL y se asigna al servicio web. Veo dos problemas potenciales:

  1. ID es un nombre muy común y puede estar reservado o puede causar conflictos. Intente cambiarle el nombre a objectId (los nombres de parámetros en mayúsculas no son la norma para .NET de todos modos)
  2. WSDL no tiene un concepto de tipos generics. Dependiendo del generador, el nombre de tipo generado para List o CustomObject[] puede entrar en conflicto con su nombre de parámetro CustomObjectList . Trate de cambiar el nombre de su segundo parámetro customObjects en customObjects lugar.

O tal vez hay otros problemas de marco tontos en juego aquí. En cualquier caso, debe agregar a su pregunta el WSDL generado por .NET. Puede obtener el WSDL XML descargando /manageobjects.asmx?WSDL desde su servidor web.

Es posible que desee revisar su elemento webServices / protocol en la sección system.web y asegurarse de que se agregue HttpPost. Normalmente, la publicación local se habilita de forma predeterminada como modo de desarrollo pero no para el control remoto, que es lo que será cuando el servicio se implemente en el servidor …

  ...       

Entro en más detalle aquí

Tal vez la ruta que está pasando con jquery no existe, intente ver la respuesta utilizando FireBug.

Siempre que recibo este tipo de errores (trabajando en local pero no en el servidor), enciendo la herramienta de administración de IIS (o lo que sea que esté usando) y verifico que todo es EXACTAMENTE igual. Si no los haces iguales entonces cambia 1 cosita a la vez.

Dependiendo de su función / organización, es posible que no tenga acceso al servidor de esta manera, pero a menudo estos errores se reducen a la checkbox aleatoria más extraña en una pestaña que nunca observa.

Es una posibilidad remota, pero no puedo evitar intentarlo.

¿Tiene registrado el httpHandler requerido para permitir que los servicios web estén marcados como ScriptService?

    

Esta es una statement incorrecta en javascript.

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

La inicialización correcta del objeto debe ser:

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

También intente eliminar temporalmente async: false de los parámetros de $.ajax .

Tengo que decir que no estoy 100% vendido. Mi respuesta es (todo) el problema, PERO esto abordaría la deserialización. Añadiendo algunos detalles para su objeto específico.

en el lado del cliente:

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

en el lado del servidor tendría: (nombre exacto de "objectSaveData") como en el código del cliente.

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

cree una clase ObjectData que contenga una lista de objectItem similar a mi otro ejemplo que hace coincidir los objetos (cuidado con los nombres).

NOTA: Tengo las extensiones ajax de ASP.NET instaladas - trabajando con el código asp.net 2.0 para este ejemplo.

Bien, así es como es para un objeto, solo probé esto: ==================================== ======== 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!"; } 

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

Y esto funciona para un solo objeto, a continuación voy a probar una lista de objetos 🙂

Asegúrese de tener esto en la parte superior de su clase

 [ScriptService] <--- this bit :D public class Surveyors : WebService 

También revise toda su parátesis, el resharper se volvió un poco loco y me tomó un tiempo verificarlo.

Además, si tiene muchos métodos web, intente hacer un servicio web básico de hello world, asegúrese de que realmente funciona en primer lugar, entonces puede solucionar los problemas desde allí.

Buena suerte.