请求参数'width'作为请求体进行提交,但GET操作不能有请求体?

7

我正在尝试从WCF REST服务获取图片,方法如下:

[ServiceContract]
public interface IReceiveData
{
    [OperationContract]
    [WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Xml, UriTemplate = "picture/")]
    //this line is wrong though
    Stream GetImage(int width, int height);
}
public class RawDataService : IReceiveData
{
    public Stream GetImage(int width, int height)
    {
        // Although this method returns a jpeg, it can be
        // modified to return any data you want within the stream
        Bitmap bitmap = new Bitmap(width, height);
        for (int i = 0; i < bitmap.Width; i++)
        {
            for (int j = 0; j < bitmap.Height; j++)
            {
                bitmap.SetPixel(i, j, (Math.Abs(i - j) < 2) ? Color.Blue : Color.Yellow);
            }
        }
        MemoryStream ms = new MemoryStream();
        bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
        ms.Position = 0;
        WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg";
        return ms;
    }
}

在我的宿主应用程序中:

class Program
    {
        static void Main(string[] args)
        {
            string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
            ServiceHost host = new ServiceHost(typeof(RawDataService), new Uri(baseAddress));
            host.AddServiceEndpoint(typeof(IReceiveData), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
            host.Open(); // this line
            Console.WriteLine("Host opened");
            Console.ReadLine();

我收到了这个错误信息:
“在协定‘IReceiveData’中,操作‘GetImage’使用GET方式,但是还有一个名为‘width’的body参数。 GET操作不能有body。要么将参数‘width’设置为UriTemplate参数,要么从WebGetAttribute切换到WebInvokeAttribute。”
我不确定如何为图像设置webinvoke / UriTemplate方法,也不知道如何获取并返回图像。可以有人发布在此示例中正确显示图像的方法吗?
编辑
如果我尝试下面的答案并在导航到`http://www.localhost.com:8000/Service/picture?width=50&height=40`时使用`UriTemplate ="picture?w={width}&h={height}"`作为我的UriTemplate,我会在代码中收到一个错误。
public Stream GetImage(int width, int height)
        {
            Bitmap bitmap = new Bitmap(width, height); // this line
            for (int i = 0; i < bitmap.Width; i++)
            {
                for (int j = 0; j < bitmap.Height; j++)
                {
                    bitmap.SetPixel(i, j, (Math.Abs(i - j) < 2) ? Color.Blue : Color.Yellow);
                }
            }
            MemoryStream ms = new MemoryStream();
            bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
            ms.Position = 0;
            WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg";
            return ms;
        }

出现了参数异常未被用户代码处理:参数无效。

2个回答

13
在属性中,您需要告诉运行时,您期望将宽度和高度作为URL参数传递。
目前,运行时假定您在不使用参数的情况下调用URL,但被调用的方法需要参数,因此运行时确实不知道如何找到要传递给您的方法的widthheight的值。
这可能看起来像:
[WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Xml, UriTemplate = "picture/{width}/{height}")]
Stream GetImage(string width, string height)
{
    int w, h;
    if (!Int32.TryParse(width, out w))
    {
        // Handle error: use default values
        w = 640;
    }
    if (!Int32.TryParse(height, out h))
    {
        // Handle error use default values
        h = 480;
    }

    ....
}

你需要像这样调用URL:http://test.tld/picture/320/200


你的方法返回:在合同'IReceiveData'中,操作'GetImage'具有名为'width'的路径变量,其类型不是'string'。UriTemplate路径段的变量必须具有'type 'string'。 - G Gr
1
你是对的,我忘记把 int 改为 string 了。URL 没有区分参数是 int 还是 string 的概念,因此所有内容都将作为 string 传递,并且您需要根据您的代码验证和转换值。无论如何,我的解决方案是正确的答案,因为我在我的一个应用程序中也有完全相同的运行 :-D - Thorsten Dittmar
1
没问题 :-) 我有时候在这里回答问题的时候会把东西缩短得太多。 - Thorsten Dittmar
1
我不是很明白你的意思... 我猜你想调用/picture,然后获取一个默认尺寸的图片?这可以通过添加另一个方法来实现,该方法不带参数并调用return GetPicture("640", "480");。 在上面的代码中,当然你会抛出异常或其他错误而不是设置默认尺寸。我只是这样做是为了让人们在出现错误时能看到一些东西正在发生。 - Thorsten Dittmar
你删除了询问如何使用默认值调用的评论 - 我上面的评论是回复那个评论的,所以现在看起来有点愚蠢。无论如何,它回答了另一个问题,即你可以做什么来能够使用默认值或传递所需的尺寸调用 picture/ - Thorsten Dittmar
显示剩余3条评论

10
UriTemplate = "picture/"
应该是这样的。
UriTemplate = "picture?w={width}&h={height}"

这告诉 WCF 如何从 URL 中获取宽度和高度参数。


这段代码可以运行,但是当我尝试访问 http://localhost:8000/Service/picture?width=50&height=40 时,会在这一行代码上出现错误:Bitmap bitmap = new Bitmap(width, height);,错误信息为 参数无效 - G Gr
1
这也是因为 {width}{height} 是字符串,而你的方法需要 int。使用我下面的解决方案,你会发现 a) URL 看起来比 Barg 的更干净,b) 在将字符串转换为 int 后,一切都能正常工作。 - Thorsten Dittmar
同时,请注意在URL和UriTemplate之间保持一致。上面的UriTemplate指定了两个名为“w”和“h”的参数,但是您的URL提供了名为“width”和“height”的参数。正确的URL应该是:http://localhost:8000/Service/picture?w=50&h=40。 - Opsimath

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接