Простой WCF POST с шаблоном Uri - PullRequest
1 голос
/ 10 октября 2011

Я думал, что это будет невероятно просто, но я должен что-то упустить. Я пытаюсь сделать простой запрос WCF POST в сочетании с UriTemplate. Я прочитал множество примеров, когда люди использовали потоковый параметр в качестве последнего параметра, и это должно было взять тело POST. Я могу заставить это работать, только если поток является единственным параметром.

Я вернулся к основам с простым сервисом Hello World.

Вот мой код на клиенте

static string Test()
{
    HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://localhost:1884/MyAPI/Service.svc/HelloWorld");
    req.Method = "POST";
    req.ContentType = "text/plain";
    Stream reqStream = req.GetRequestStream();
    byte[] fileToSend = System.Text.UTF8Encoding.UTF8.GetBytes("sometext");
    reqStream.Write(fileToSend, 0, fileToSend.Length);
    reqStream.Close();
    HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
    var sr = new StreamReader(resp.GetResponseStream());
    return sr.ReadToEnd();
}

А это код на сервисе

[ServiceContract]
public interface IService
{
    [OperationContract]
    [WebInvoke(Method = "POST", UriTemplate = "HelloWorld")]
    Stream HelloWorld(Stream content);
}

public Stream HelloWorld(Stream content)
{
    var sr = new StreamReader(content);
    string text = sr.ReadToEnd();
    return new System.IO.MemoryStream(Encoding.UTF8.GetBytes("Hello World! " + text)); 
}

Это все отлично работает. Затем я делаю это изменение:

[ServiceContract]
public interface IService
{
    [OperationContract]
    [WebInvoke(Method = "POST", UriTemplate = "HelloWorld/test/{test}")]
    Stream HelloWorld(string test, Stream content);
}

public Stream HelloWorld(string test, Stream content)
{
    var sr = new StreamReader(content);
    string text = sr.ReadToEnd();
    return new System.IO.MemoryStream(Encoding.UTF8.GetBytes("Hello World! " + text + test)); 
}

И измените клиентский код на HelloWorld / test / sometext

Я получаю 500 Внутренняя ошибка сервера. Я пробовал около 10 различных вариантов, включая использование? Key = value type UriTemplate, возвращение строк вместо потоков и т. Д., И не повезло.

Чувствуется, что мне не хватает какой-то крошечной вещицы, которая сделает эту работу, поскольку я видел бесчисленные примеры именно этого по всей сети. Они работают, мои нет.

Есть идеи?

Ответы [ 3 ]

2 голосов
/ 16 ноября 2011

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

Правка: в конце мы обнаружили, что нам нужно было указать WebServiceHostFactory в Service.svc.Это было по умолчанию в новом проекте

0 голосов
/ 11 октября 2011

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

using System.IO;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Text;

namespace StreamService
{
    [ServiceContract]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class MergedEndpoint
    {
        [WebGet(RequestFormat = WebMessageFormat.Xml, UriTemplate = "Data/{someid}",
          ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
        public string GetData(string someid)
        {
            return string.Format("You entered: {0}", someid);
        }

          [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, UriTemplate = "HelloWorld",
          ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
        public Stream HelloWorld1(Stream content)
        {
            var sr = new StreamReader(content);
            string text = sr.ReadToEnd();
            return new System.IO.MemoryStream(Encoding.UTF8.GetBytes("Hello World from single file! " + text));
        }
         [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, UriTemplate = "HelloWorld/test/{testparam}",
          ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
          public Stream HelloWorld2(string testparam, Stream content)
        {
            var sr = new StreamReader(content);
            string text = sr.ReadToEnd();
            return new System.IO.MemoryStream(Encoding.UTF8.GetBytes("Hello World from single file! " + testparam+ text));
        }
    }
}

Входные параметры должны иметь то же имя, что и параметры метода.Их тип также является строкой.Вам нужно выполнить преобразование, если вы хотите ввести другой параметр ввода.

Вам необходимо создать проект WCf и добавить файл Global.asax с информацией о маршрутизации для этого файла.Возможно, вам потребуется добавить ссылку на System.ServiceModel.Activation для настройки маршрутизации.Пример:

protected void Application_Start(object sender, EventArgs e)
        {
 RegisterRoutes();
        }


        private void RegisterRoutes()
        {


            RouteTable.Routes.Add(new ServiceRoute("MergedEndpoint", new WebServiceHostFactory(), typeof(MergedEndpoint)));

    }

В коде вашего клиента есть одно изменение типа контента.

 HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("http://localhost:55166/MergedEndpoint/HelloWorld/test/234");
            req.Method = "POST";
            //req.ContentType = "text/plain";
            req.MediaType = "HTTP/1.1";
            req.ContentType = "application/json; charset=utf-8";
            Stream reqStream = req.GetRequestStream();
            byte[] fileToSend = System.Text.UTF8Encoding.UTF8.GetBytes("sometext");
            reqStream.Write(fileToSend, 0, fileToSend.Length);
            reqStream.Close();
            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            var sr = new StreamReader(resp.GetResponseStream());
            string outp = sr.ReadToEnd();
            Console.WriteLine("Response:"+outp);

Вы можете читать необработанный контент, даже если для него задан тип Json.

0 голосов
/ 10 октября 2011

При потоковой передаче поток должен быть единственным параметром: http://msdn.microsoft.com/en-us/library/ms789010.aspx

Вы можете использовать заголовки сообщений: Добавить имя файла и параметр длины в поток WCF, когда Transfermode = Stream

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...