RESTful WCF Service That Needs to Upload Images And Multiple Arguments
I am in the process of developing a WCF service that needs to take in an image and 2 parameters. One being an int type, the other a string array. So this would be easy enough if it were only 1 parameter to send up, along with the image:
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "UploadImages/{imageID}")]
public void UploadImages(int imageID, Stream image)
{
}
Now, in this scenario the image is in the body of the post. What if the consumer of the service needs to pass up a开发者_Python百科 third piece of data, how does that look and work in WCF?
<system.serviceModel>
<client>
</client>
<bindings>
<webHttpBinding>
<binding name="webHttpBindingStreamed" transferMode="Streamed"></binding>
</webHttpBinding>
</bindings>
<services>
<service name="ImageService">
<endpoint address="" binding="webHttpBinding" behaviorConfiguration="MyWebHttpBehavior" name="ImageServiceWebBinding" contract=IImageService" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="MyWebHttpBehavior">
<customWebHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="customWebHttp" type="CustomHttpBehaviorExtensionElement, ImageUploader" />
</behaviorExtensions>
</extensions>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
You can pass the additional parameters in the URI as well, like in the example below. Or you can pass them as HTTP headers and fetch them using the WebOperationContext.Current.IncomingRequest.Headers
property.
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "UploadImages/{fileName}?imageId={imageID}")]
public void UploadImages(int imageID, string fileName, Stream image)
{
}
Update
Even if the parameter type is an array, you can also pass it in the query string - but you'll need to provide a QueryStringConverter
which can decode that type. The example below shows that.
public class StackOverflow_6905108
{
[ServiceContract]
public class Service
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "UploadImages/{fileName}?array={array}")]
public void UploadImages(int[] array, string fileName, Stream image)
{
Console.WriteLine("Array:");
foreach (var item in array) Console.Write("{0} ", item);
Console.WriteLine();
}
}
public static void SendPost(string uri, string contentType, string body)
{
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uri);
req.Method = "POST";
req.ContentType = contentType;
Stream reqStream = req.GetRequestStream();
byte[] reqBytes = Encoding.UTF8.GetBytes(body);
reqStream.Write(reqBytes, 0, reqBytes.Length);
reqStream.Close();
HttpWebResponse resp;
try
{
resp = (HttpWebResponse)req.GetResponse();
}
catch (WebException e)
{
resp = (HttpWebResponse)e.Response;
}
Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription);
foreach (string headerName in resp.Headers.AllKeys)
{
Console.WriteLine("{0}: {1}", headerName, resp.Headers[headerName]);
}
Console.WriteLine();
Stream respStream = resp.GetResponseStream();
Console.WriteLine(new StreamReader(respStream).ReadToEnd());
Console.WriteLine();
Console.WriteLine(" *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* ");
Console.WriteLine();
}
class MyQueryStringConverter : QueryStringConverter
{
QueryStringConverter originalConverter;
public MyQueryStringConverter(QueryStringConverter originalConverter)
{
this.originalConverter = originalConverter;
}
public override bool CanConvert(Type type)
{
return type == typeof(int[]) || base.CanConvert(type);
}
public override object ConvertStringToValue(string parameter, Type parameterType)
{
if (parameterType == typeof(int[]))
{
return parameter.Split(',').Select(x => int.Parse(x)).ToArray();
}
else
{
return base.ConvertStringToValue(parameter, parameterType);
}
}
}
public class MyWebHttpBehavior : WebHttpBehavior
{
protected override QueryStringConverter GetQueryStringConverter(OperationDescription operationDescription)
{
return new MyQueryStringConverter(base.GetQueryStringConverter(operationDescription));
}
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
host.AddServiceEndpoint(typeof(Service), new WebHttpBinding(), "").Behaviors.Add(new MyWebHttpBehavior());
host.Open();
Console.WriteLine("Host opened");
SendPost(baseAddress + "/UploadImages/a.txt?array=1,2,3,4", "application/octet-stream", "The file contents");
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}
精彩评论