Необязательный параметр в методе службы asmx приводит к отказу другого метода

Чтобы воссоздать проблему, которую я вижу, используя VS2010, создайте пустой веб-сайт и добавьте веб-службу (asmx) с кодом.

Используя следующий код, оба веб-метода могут быть успешно задействованы:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService {
    [WebMethod]
    public void Method1(int x) {
        // i'm good
    }
    [WebMethod]
    public string Method2(int x) {
        return "it worked";
    }
}

Теперь, если я изменю parm на методе 2 на тип с нулевым значением, он будет работать нормально, но это сделает отказ метода 1...

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService {
    [WebMethod]
    public void Method1(int x) {
        // no changes made to this method, but it no longer works
    }
    [WebMethod]
    public string Method2(int? x) {
        return "it worked";
    }
}

Результирующая ошибка - это та, которую я видел раньше, если при вызове службы отсутствует параметр:

System.IndexOutOfRangeException: индекс находился за пределами массив. в System.Web.Services.Protocols.HttpServerType..ctor(Тип типа) при System.Web.Services.Protocols.HttpServerProtocol.Initialize() at System.Web.Services.Protocols.ServerProtocolFactory.Create(Тип типа, Контекст HttpContext, запрос HttpRequest, ответ HttpResponse, Логическое & abortProcessing)

Кроме того, это только кажется сломанным, если первый метод возвращает void, поэтому это также отлично работает:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService {
    [WebMethod]
    public string Method1(int x) {
        return "works again";
    }
    [WebMethod]
    public string Method2(int? x) {
        return "it worked";
    }
}

Любые идеи, что здесь происходит? Это произошло с использованием как 3.5, так и 4.0 в качестве целевой структуры.

edit: просто чтобы упредить дальнейшие ответы/комментарии по этим строкам... Я не ищу советы о лучших практиках, альтернативных решениях, asmx-месте в ландшафте сервиса, wcf и т.д. Это то, что я пришел во время отладки проблемы в устаревшем приложении, которое я не писал и которое уже исправлено, и мне интересно узнать причину конкретного поведения, которое я здесь изложил.

Ответы

Ответ 1

@heisenberg, вы передаете null из приложения, которое вызывает веб-метод. Образец, который я пробовал, отлично работает на vs2010. ниже этого кода, который я пробовал.

Пример кода:

 protected void Button1_Click(object sender, EventArgs e)
    {
        WebService1 objws = new WebService1();
        objws.voidMethod(5);
        Label1.Text = objws.HelloWorld(5);
    }

Код службы ASMX

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService1 : System.Web.Services.WebService
{
    [WebMethod]
    public string HelloWorld(int? x)
    {
        if (x != null)
        {
            return x.ToString();
        }
        return "Hello World";
    }

    [WebMethod]
    public void voidMethod(int x)
    {

    }
}

Ответ 2

Я пробовал ваш код, и он работает. Хотя отладка не работает, возникает ошибка.

Я думаю, что это происходит потому, что Nullable int не является примитивным типом. См. Описание из WSDL службы "Тестовая форма доступна только для методов с примитивными типами в качестве параметров".

Я предполагаю, что проблема, с которой вы сталкиваетесь, происходит не из-за Nullable int.

[WebService(Namespace = "http://tempuri.org/")]

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]

[System.ComponentModel.ToolboxItem(false)]

public class WebService1 : System.Web.Services.WebService
{
    [WebMethod]
    public void Method1(int x)
    {
        // i'm good
    }
    [WebMethod]
    public string Method2(int? x)
    {
        return "it worked";
    }
}

Код сайта:

namespace Helper
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            ServiceReference1.WebService1SoapClient web = new ServiceReference1.WebService1SoapClient();
            web.Method1(5);

            string x = web.Method2(5);
        }
    }
}

Ответ 3

Это может случиться, может быть, вы пытаетесь отправить один и тот же X на оба метода, хотя они не принимают один и тот же тип?

потому что одно значение равно null, а другое - нет.

Ответ 4

Нужно ли использовать Nullable (?) в вашем решении? Я думаю, что вы можете реализовать очень простую логику, например: "Если я получаю пустую строку, то у меня есть значение Null или если я получаю строковое значение" Null ", то мне нужно использовать Null Object", и в будущем рассмотрим использование WCF с подходом Nullable-?.

С другой стороны, я рекомендую вам изменить все методы void на строковое значение со словом "ok". Я думаю, что "запрос должен иметь ответ".