Step 1: Create a New WCF Service Project (WCF Service Library).
- On the File menu, click New Project.
- In the New Project dialog box under Project types, expand Visual C#, click WCF and select WCF Service Library. In the Name box, type "DemoMultipartWCF". In the Solution name, type "WCFDemo" and then click OK.
- Now, delete the default created Interface, Class perspective "IService1.cs" and "Service1.cs".
- Add a New Interface by right clicking on DemoMultipartWCF(project) > Add > New Item and select "WCF Service". Name it as "Users.svc", click ADD.
Step 2: Create an Interface and implement its body.
- Create a New Interface in IUsers.cs File (Paste the code, given below):
- [OperationContract]
- [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedResponse, UriTemplate = "UpdateUserDetail")]
- bool UpdateUserDetail(Stream stream);
- Implement the body of UpdateUserDetail Interface in Users.svc file (Paste the code, given below):
- public bool UpdateUserDetail(Stream stream)
- {
- return false;
- }
Step 3: Create a MultipartParser to read the requested form data.
Create a New folder name as "DataContract" in your project, add "CommonDC" class in the folder. Paste the code, given below, in "CommonDC.cs File" class.
Uses Of All Below Method
- Parse (Stream stream, Encoding encoding) - This method is used to check the input stream in UTF8 (Unicode Transformation Format).
- ParseParameter (Stream stream, Encoding encoding) - This method is used to parse the parameter from the stream
IndexOf(byte[] searchWithin, byte[] serachFor, int startIndex) - This method is separate from all the requested parameters, which are in the stream.
- ToByteArray(Stream stream) - This method is used to convert the stream to byteArray
- public class MultipartParser {
- private byte[] requestData;
-
- public MultipartParser(Stream stream) {
-
- this.Parse(stream, Encoding.UTF8);
- ParseParameter(stream, Encoding.UTF8);
- }
- public MultipartParser(Stream stream, Encoding encoding) {
- this.Parse(stream, encoding);
- }
- private void Parse(Stream stream, Encoding encoding) {
- this.Success = false;
-
- byte[] data = ToByteArray(stream);
- requestData = data;
-
- string content = encoding.GetString(data);
-
- int delimiterEndIndex = content.IndexOf("\r\n");
- if (delimiterEndIndex > -1) {
- string delimiter = content.Substring(0, content.IndexOf("\r\n"));
-
-
- Regex re = new Regex(@ "(?<=Content\-Type:)(.*?)(?=\r\n\r\n)");
- Match contentTypeMatch = re.Match(content);
-
- re = new Regex(@ "(?<=filename\=\"")(.* ? )( ? = \"")
- ");
- Match filenameMatch = re.Match(content);
-
- if (contentTypeMatch.Success && filenameMatch.Success) {
-
- this.ContentType = contentTypeMatch.Value.Trim();
- this.Filename = filenameMatch.Value.Trim();
-
- int startIndex = contentTypeMatch.Index + contentTypeMatch.Length + "\r\n\r\n".Length;
- byte[] delimiterBytes = encoding.GetBytes("\r\n" + delimiter);
- int endIndex = IndexOf(data, delimiterBytes, startIndex);
- int contentLength = endIndex - startIndex;
-
- byte[] fileData = new byte[contentLength];
- Buffer.BlockCopy(data, startIndex, fileData, 0, contentLength);
- this.FileContents = fileData;
- this.Success = true;
- }
- }
- }
- private void ParseParameter(Stream stream, Encoding encoding) {
- this.Success = false;
-
- byte[] data;
- if (requestData.Length == 0) {
- data = ToByteArray(stream);
- } else {
- data = requestData;
- }
-
- string content = encoding.GetString(data);
-
- int delimiterEndIndex = content.IndexOf("\r\n");
- if (delimiterEndIndex > -1) {
- string delimiter = content.Substring(0, content.IndexOf("\r\n"));
- string[] splitContents = content.Split(new [] {
- delimiter
- }, StringSplitOptions.RemoveEmptyEntries);
- foreach(string t in splitContents) {
-
- Regex contentTypeRegex = new Regex(@ "(?<=Content\-Type:)(.*?)(?=\r\n\r\n)");
- Match contentTypeMatch = contentTypeRegex.Match(t);
-
- Regex re = new Regex(@ "(?<=name\=\"")(.*)
- ");
- Match name = re.Match(t);
-
- re = new Regex(@ "(?<=filename\=\"")(.* ? )( ? = \"")
- ");
- Match filenameMatch = re.Match(t);
-
- if (name.Success || filenameMatch.Success) {
-
-
- int startIndex;
- if (filenameMatch.Success) {
- this.Filename = filenameMatch.Value.Trim();
- }
- if (contentTypeMatch.Success) {
-
- startIndex = contentTypeMatch.Index + contentTypeMatch.Length + "\r\n\r\n".Length;
- } else {
- startIndex = name.Index + name.Length + "\r\n\r\n".Length;
- }
-
-
-
- string propertyData = t.Substring(startIndex - 1, t.Length - startIndex);
-
-
-
- MyContent myContent = new MyContent();
- myContent.Data = encoding.GetBytes(propertyData);
- myContent.StringData = propertyData;
- myContent.PropertyName = name.Value.Trim().TrimEnd('"');
- if (MyContents == null) MyContents = new List < MyContent > ();
- MyContents.Add(myContent);
- this.Success = true;
- }
- }
- }
- }
- private int IndexOf(byte[] searchWithin, byte[] serachFor, int startIndex) {
- int index = 0;
- int startPos = Array.IndexOf(searchWithin, serachFor[0], startIndex);
- if (startPos != -1) {
- while ((startPos + index) < searchWithin.Length) {
- if (searchWithin[startPos + index] == serachFor[index]) {
- index++;
- if (index == serachFor.Length) {
- return startPos;
- }
- } else {
- startPos = Array.IndexOf < byte > (searchWithin, serachFor[0], startPos + index);
- if (startPos == -1) {
- return -1;
- }
- index = 0;
- }
- }
- }
- return -1;
- }
- private byte[] ToByteArray(Stream stream) {
- byte[] buffer = new byte[32768];
- using(MemoryStream ms = new MemoryStream()) {
- while (true) {
- int read = stream.Read(buffer, 0, buffer.Length);
- if (read <= 0) return ms.ToArray();
- ms.Write(buffer, 0, read);
- }
- }
- }
- public List < MyContent > MyContents {
- get;
- set;
- }
- public bool Success {
- get;
- private set;
- }
- public string ContentType {
- get;
- private set;
- }
- public string Filename {
- get;
- private set;
- }
- public byte[] FileContents {
- get;
- private set;
- }
- }
- public class MyContent {
- public byte[] Data {
- get;
- set;
- }
- public string PropertyName {
- get;
- set;
- }
- public string StringData {
- get;
- set;
- }
- }
Step 4: Implement Pre-Required Method like SaveImageFile & GetEncoder.
- Create a Method to save the image file.
- public static bool SaveImageFile(byte[] ImageFileContent, string ImagePathWithImageName)
- {
- try {
-
- Image image;
-
- using(MemoryStream ms = new MemoryStream(ImageFileContent)) {
- image = Image.FromStream(ms);
- }
- Bitmap bmp = new Bitmap(image);
-
- ImageCodecInfo jgpEncoder = GetEncoder(ImageFormat.Jpeg);
-
- System.Drawing.Imaging.Encoder myEncoder = System.Drawing.Imaging.Encoder.Quality;
- EncoderParameters myEncoderParameters = new EncoderParameters(1);
- EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 40 L);
- myEncoderParameters.Param[0] = myEncoderParameter;
- bmp.Save(ImagePathWithImageName, jgpEncoder, myEncoderParameters);
- return true;
- } catch {
-
- return false;
- }
- }
Note: We need to write Encoder with Root, else it is an ambiguity between "System.Drawing.Imaging.Encoder" and "System.Text.Encoder".
- Create a method to retrieve the image codecs.
- public static ImageCodecInfo GetEncoder(ImageFormat format)
- {
- ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
- foreach(ImageCodecInfo codec in codecs) {
- if (codec.FormatID == format.Guid) {
- return codec;
- }
- }
- return null;
- }
What is the use of ImageCodecInfo ?
It provides the necessary storage members and methods to retrieve all the pertinent information about the installed image codecs.
Step 5: Now, it's time to implement our interface - UpdateUserDetail. (Paste the code, given below):
- public bool UpdateUserDetail(Stream stream) {
- try {
-
- byte[] buf = new byte[10000000];
-
- MultipartParser parser = new MultipartParser(stream);
-
- if (parser != null && parser.Success) {
-
-
- foreach(var item in parser.MyContents) {
-
- if (item.PropertyName == "UserName") {
- string RequestedName = item.StringData;
- }
- }
-
- string ImageName = Guid.NewGuid().ToString();
-
- string SaveImagePath = "D:/DemoProject/DemoMultipartWCF/DemoMultipartWCF/MyFile/";
-
- if (!Directory.Exists(SaveImagePath)) {
-
- Directory.CreateDirectory(SaveImagePath);
- }
-
- string ImagePathWithImageName = SaveImagePath + ImageName + ".bmp";
- SaveImageFile(parser.FileContents, ImagePathWithImageName);
- return true;
- }
- return false;
- } catch {
-
- return false;
- }
- }
Step 6: Now, all is done. Ensure you have the following setting in your Web.config:
- <system.serviceModel>
- <bindings>
- <basicHttpBinding>
- <binding maxReceivedMessageSize="999999999" maxBufferSize="999999999" maxBufferPoolSize="9999999999" name="ITransactionProcessor">
- <readerQuotas maxDepth="32" maxArrayLength="999999999" maxStringContentLength="999999999" />
- <security mode="TransportWithMessageCredential" /> </binding>
- </basicHttpBinding>
- </bindings>
- <behaviors>
- <serviceBehaviors>
- <behavior>
-
- <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
-
- <serviceDebug includeExceptionDetailInFaults="true" /> </behavior>
- </serviceBehaviors>
- <endpointBehaviors>
- <behavior name="web">
- <webHttp helpEnabled="true" /> </behavior>
- </endpointBehaviors>
- </behaviors>
- <protocolMapping>
- <add binding="basicHttpsBinding" scheme="https" /> </protocolMapping>
- <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
- <services>
- <service name="DemoMultipartWCF.Users">
- <endpoint name="UsersXML" address="" binding="basicHttpBinding" contract="DemoMultipartWCF.IUsers"></endpoint>
- <endpoint name="UsersJSON" address="json" binding="webHttpBinding" contract="DemoMultipartWCF.IUsers" behaviorConfiguration="web"></endpoint>
- </service>
- </services>
- <client>
- <endpoint address="https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor" binding="basicHttpBinding" bindingConfiguration="ITransactionProcessor" contract="com.cybersource.api.ITransactionProcessor" name="portXML" /> </client>
- </system.serviceModel>
Now, it's complementary time.
How To Test This WCF Service ? - You Need to install POSTMAN or ADVANCE REST SHARP in Chrome Browser. (There are also some other tools, available to test WCF Services).
- Open Postman and enter the requested URL.
- Select POST Method.
- Select Body and Fill Form Data. (Requested Data: Username & Requested File: ProfilePicture [browse and select the image]).
- Now, just hit Send and here we go.