Веб-метод ASP.NET, принимающий список <CustomObject>, завершается с ошибкой «Недопустимое имя метода веб-службы». - PullRequest
6 голосов
/ 09 февраля 2010

Я хочу создать веб-метод, который принимает список пользовательских объектов (передаваемых через jQuery / JSON).

Когда я запускаю сайт локально, кажется, что все работает. jQuery и ASP.NET и все счастливы. Но когда я ставлю его на один из наших серверов, он взрывается. jQuery получает ошибку 500 после ajax-запроса с ответом:

System.InvalidOperationException: Недопустимое имя метода веб-службы EditCustomObjects.

Вот метод веб-службы:

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

И мой код jQuery (который, я думаю, не имеет значения, поскольку, похоже, ошибка происходит на уровне веб-службы):

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? Есть ли способ решить «Недопустимое имя метода веб-службы». ошибка?

К вашему сведению, я запускаю .NET 2.0 на компьютере с Windows Server 2003 и получил код для вышеупомянутого с этого сайта: 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 ]

4 голосов
/ 15 февраля 2010

Я делаю предположение на основе комментариев, которые вы можете напрямую перейти на веб-сервис в браузере.

Просто для того, чтобы изолировать ваш пользовательский объект от конфигурации, вы можете установить другой сервис, например:

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

ПРИМЕЧАНИЕ! ВАЖНО! Для правильной работы этого имени имя процедуры instanceSave должно точно совпадать на стороне клиента и сервера. РЕДАКТИРОВАТЬ3: больше пример кода:

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 голос
/ 20 февраля 2010

Поскольку ошибка упоминает о проблеме с именем веб-метода, я подозреваю, что это полностью связано с проблемами в том, как WSDL генерируется и сопоставляется с веб-службой. Я вижу две потенциальные проблемы:

  1. ID является очень распространенным именем и может быть зарезервировано или может вызывать конфликты. Попробуйте переименовать его в objectId (заглавные имена параметров не являются нормой для .NET в любом случае)
  2. WSDL не имеет понятия универсальных типов. В зависимости от генератора имя типа, сгенерированное для List<CustomObject> или CustomObject[], может конфликтовать с именем вашего параметра CustomObjectList. Попробуйте вместо этого переименовать второй параметр customObjects.

Или, может быть, здесь есть и другие глупые проблемы с фреймворком. В любом случае, вы должны добавить к своему вопросу WSDL, сгенерированный .NET. Вы можете получить WSDL XML, загрузив /manageobjects.asmx?WSDL с вашего веб-сервера.

0 голосов
/ 05 марта 2014

Убедитесь, что у вас есть это на вершине вашего класса

[ScriptService] <--- this bit :D

public class Surveyors : WebService

Также проверь все свои паратезы, резарпер сошел с ума от меня, и потребовалось некоторое время, чтобы проверить.

Кроме того, если у вас много веб-методов, попробуйте сделать базовый веб-сервис hello world, убедитесь, что он действительно работает в первую очередь, тогда вы можете устранить неполадки оттуда.

Удачи.

0 голосов
/ 22 марта 2012

Хорошо, вот как это для объекта, только что проверил это: ============================================ 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!";
}

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

И это работает для одного объекта, далее я собираюсь попробовать список объектов:)

0 голосов
/ 16 февраля 2010

Должен сказать, что я не продан на 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.

0 голосов
/ 16 февраля 2010

Это неправильное объявление в javascript.

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

Правильная инициализация объекта должна быть:

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

Также попробуйте временно удалить async: false из параметров $.ajax.

0 голосов
/ 15 февраля 2010

У вас есть зарегистрированный httpHandler для разрешения веб-сервисам, помеченным как ScriptService?

<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>
0 голосов
/ 15 февраля 2010

Всякий раз, когда я получаю такие ошибки (работая на локальном сервере, но не на сервере), я запускаю инструмент администрирования IIS (или все, что вы используете) и проверяю, что все точно так же. Если не сделать их одинаковыми, замените 1 мелочь за раз.

В зависимости от вашей роли / организации у вас может не быть доступа к серверу таким образом, но часто эти ошибки сводятся к самому странному случайному флажку на вкладке, на которую вы никогда не обращали внимания.

Это длинный выстрел, но не могу помочь.

0 голосов
/ 14 февраля 2010

Возможно, путь, который вы передаете с помощью jquery, не существует, попробуйте просмотреть ответ с помощью FireBug.

0 голосов
/ 10 февраля 2010

Возможно, вы захотите проверить свой элемент webServices / protocol в разделе system.web и убедиться, что HttpPost добавлен. Как правило, локальная публикация по умолчанию включена как режим разработки, но не для удаленной, что и происходит при развертывании службы на сервере ...

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

Я вхожу более подробно здесь

...