{"id":285,"date":"2011-08-17T18:40:08","date_gmt":"2011-08-17T18:40:08","guid":{"rendered":"https:\/\/blogs.mathworks.com\/loren\/2011\/08\/17\/builder-ne-and-the-windows-communication-foundation\/"},"modified":"2011-08-22T11:09:08","modified_gmt":"2011-08-22T11:09:08","slug":"builder-ne-and-the-windows-communication-foundation","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/loren\/2011\/08\/17\/builder-ne-and-the-windows-communication-foundation\/","title":{"rendered":"Deploying MATLAB Functions as .NET Web Services"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <introduction>\r\n      <p>Guest blogger <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/authors\/4660\">Peter Webb<\/a> returns with another in an <a href=\"https:\/\/blogs.mathworks.com\/loren\/category\/deployment\/\">occasional series<\/a> of postings about application deployment.\r\n      <\/p>\r\n   <\/introduction>\r\n   <h3>Contents<\/h3>\r\n   <div>\r\n      <ul>\r\n         <li><a href=\"#1\">Publishing a MATLAB Function as a Web Service<\/a><\/li>\r\n         <li><a href=\"#2\">WCF-Enabling a Type Safe API<\/a><\/li>\r\n         <li><a href=\"#3\">A MATLAB-based WCF Server<\/a><\/li>\r\n         <li><a href=\"#4\">A C# Client Program<\/a><\/li>\r\n         <li><a href=\"#5\">Building and Running the Example<\/a><\/li>\r\n         <li><a href=\"#6\">WCF Support Enables New Kinds of Deployment<\/a><\/li>\r\n      <\/ul>\r\n   <\/div>\r\n   <h3>Publishing a MATLAB Function as a Web Service<a name=\"1\"><\/a><\/h3>\r\n   <p>Imagine that I've written a great <a href=\"https:\/\/www.mathworks.com\/products\/matlab\/\">MATLAB<\/a> application and deployed it as a <a href=\"https:\/\/www.mathworks.com\/products\/netbuilder\/\">.NET application<\/a>. Lots of people use it, and now I've been asked to make it available via the web. Since it has no GUI, I don't want to run\r\n      it in a browser. I'd like to publish it as a <a href=\"http:\/\/en.wikipedia.org\/wiki\/Web_service\"><i>web service<\/i><\/a> so remote clients can take advantage of its computational prowess. But that means I'll have to send MATLAB matrices back\r\n      and forth across the network, a challenging coding task. Deployed type safe APIs allow me to integrate seamlessly with Microsoft's\r\n      <a href=\"http:\/\/msdn.microsoft.com\/en-us\/netframework\/aa663324\">Windows Communication Foundation<\/a> (WCF), automating most of that work for me.\r\n   <\/p>\r\n   <p>I'll demonstrate how this works with an application that consists of four parts:<\/p>\r\n   <li>A WCF-enabled type safe API.<\/li>\r\n   <li>A deployed MATLAB C# component implementing the type safe API.<\/li>\r\n   <li>A server application that publishes the service to client applications.<\/li>\r\n   <li>A client application that consumes the published service.<\/li>\r\n   <h3>WCF-Enabling a Type Safe API<a name=\"2\"><\/a><\/h3>\r\n   <p>My MATLAB program generates the outline of a simple fractal, the <a href=\"http:\/\/en.wikipedia.org\/wiki\/Koch_snowflake\">Koch snowflake<\/a>, which consists entirely of straight lines. The program exports a single function:\r\n   <\/p><pre>function [vectors, bbox] = snowflake(n, width, height)<\/pre><p><tt>snowflake<\/tt> returns the <tt>n<\/tt>-th iteration of the outline as a series of two-dimensional <tt>vectors<\/tt>, scaled to fit within a rectangle of <tt>width<\/tt> by <tt>height<\/tt> units. The second output, <tt>bbox<\/tt>, specifies a rectangle that fits tightly around the outline.\r\n   <\/p>\r\n   <p>From my C# client, I'd like to call <tt>snowflake<\/tt> with integer inputs and outputs. The inputs are scalars, so I declare them as simple integers. The first output, <tt>vectors<\/tt>, is a vector of vectors (a matrix!), while the second, <tt>bbox<\/tt> is a 4-element vector. I declare my C# <tt>snowflake<\/tt> function within a new interface, <tt>IFractal<\/tt>:\r\n   <\/p><pre>public interface IFractal\r\n{\r\n  int[][] snowflake(out int[] bbox, int n, int width, int height);\r\n}<\/pre><p>Both C# and WCF support multi-dimensional arrays, but WCF requires the <i>jagged<\/i> array storage format. As a result, I declare <tt>snowflake<\/tt>'s return value <tt>int[][]<\/tt> (a jagged array) instead of C#'s more efficient <tt>int[,]<\/tt>.\r\n   <\/p>\r\n   <p>I need to make two more changes to web-enable this type safe API: I decorate both the interface and the function with WCF-specific\r\n      <a title=\"http:\/\/msdn.microsoft.com\/en-us\/library\/z0w1kczw%28v=vs.80%29.aspx (link no longer works)\"><i>attributes<\/i><\/a> asserting that the function provides an <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.servicemodel.operationcontractattribute.aspx\"><i>operation<\/i><\/a> as part of a web <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.servicemodel.servicecontractattribute.aspx\"><i>service<\/i><\/a>.\r\n   <\/p><pre>[ServiceContract]\r\npublic interface IFractal\r\n{\r\n    [OperationContract(Name = \"snowflake\")]\r\n    int[][] snowflake(out int[] bbox, int n, int width, int height);\r\n}<\/pre><p>If your service interface exposes overloaded functions as operations, you must give each a unique <tt>Name<\/tt>.\r\n   <\/p>\r\n   <h3>A MATLAB-based WCF Server<a name=\"3\"><\/a><\/h3>\r\n   <p>A WCF service needs a <i>host<\/i>, a server program that listens for and responds to client requests. Each request asks the server to perform an operation\r\n      defined by a service contract based on a WCF-enabled .NET interface. My server hosts a single service, <tt>Snowflake.KochIFractal<\/tt>, based on the <tt>IFractal<\/tt> interface.\r\n   <\/p>\r\n   <p>I create my <tt>snowflake<\/tt> server, <tt>KochServer<\/tt>, in three steps:\r\n   <\/p>\r\n   <li>Deploy <tt>snowflake<\/tt> into a .NET assembly implementing a type safe API based on <tt>IFractal<\/tt>.\r\n   <\/li>\r\n   <li>Define a service named <tt>Snowflake.KochIFractal<\/tt> that exposes the <tt>IFractal<\/tt> interface.\r\n   <\/li>\r\n   <li>Create a .NET <tt>ServiceHost<\/tt> object that hosts the <tt>Snowflake.KochIFractal<\/tt> service.\r\n   <\/li>\r\n   <p>The first step is easy: I create deploytool project using Builder NE and generate a type safe API using <tt>IFractal<\/tt>. (I covered this process in detail in my first type safe API post.)\r\n   <\/p>\r\n   <p>The second and third steps require a little knowledge of WCF servers. The simplest type of servers (<a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bb332338.aspx\">self-hosted<\/a>) consist of a <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms731734.aspx\"> WCF service configuration file<\/a> and a managed .NET application. The configuration file defines the services hosted by the managed application.\r\n   <\/p>\r\n   <p>The configuration file describes each service and its behaviors, identifying <i>endpoints<\/i> from which clients can request operations. For example, <tt>KochServer<\/tt>'s configuration file, <tt>App.config<\/tt>, exposes the <tt>IFractal<\/tt> interface through an endpoint named <tt>HttpBinding<\/tt>.\r\n   <\/p><pre>&lt;endpoint\r\n     address=\"\"\r\n     binding=\"wsHttpBinding\"\r\n     bindingConfiguration=\"wsHttpConfig\"\r\n     contract=\"IFractal\"\r\n     name=\"HttpBinding\" \/&gt;<\/pre><p>I derived <tt>KochServer<\/tt>'s configuration file from the configuration file that ships with the WCF example. You can do the same; just make sure to\r\n      edit the configuration file to reflect the name of your service and your endpoint <tt>contract<\/tt>.\r\n   <\/p>\r\n   <p>The managed application, the host program itself, can be as simple as a .NET console application. Create a conole application\r\n      project, add the configuration file to the project and then, in your <tt>Main<\/tt> function, create a <tt>ServiceHost<\/tt> object for your service. <tt>KochServer<\/tt> creates a <tt>ServiceHost<\/tt> for <tt>Snowflake.KochIFractal<\/tt>, the service defined in <tt>KochServer<\/tt>'s configuration file.\r\n   <\/p><pre>ServiceHost host = new ServiceHost(typeof(Snowflake.KochIFractal))<\/pre><p>A self-hosted service must start and stop the service somehow. <tt>KochServer<\/tt> starts the service when the server program starts and then waits for the user to press a key; the first keystroke stops the\r\n      service. Your services will probably start and stop using more sophisticated mechanisms.\r\n   <\/p>\r\n   <h3>A C# Client Program<a name=\"4\"><\/a><\/h3>\r\n   <p>The client program renders the Koch snowflake into a Windows form with the native .NET drawing API (the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.drawing.aspx\">System.Drawing namespace<\/a>). Like the server, the client is a standard .NET console application. The client interacts with the server via a <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms730144%28v=VS.90%29.aspx\"><i>proxy<\/i><\/a>, an object that manages the actual network connection to the <tt>KochServer<\/tt>. Since writing a proxy is an exercise in boiler-plate tedium, Microsoft provides a tool, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa347733%28v=VS.90%29.aspx\"><tt>svcutil.exe<\/tt><\/a>, that automatically generates proxies from services. I started <tt>KochServer<\/tt>, then ran this <tt>svcutil<\/tt> command:\r\n   <\/p><pre> svcutil \/t:code http:\/\/localhost:8001\/KochServer\/\r\n         \/out:FractalClient.cs \/config:App.config<\/pre><p><tt>svcutil<\/tt> generated a C# proxy class, <tt>FractalClient<\/tt>, and a configuration file, <tt>App.config<\/tt>, for my client program. I added both of these files to my <tt>KochClient<\/tt> Visual Studio project.\r\n   <\/p>\r\n   <p>In my client's <tt>Main<\/tt> method, I create a <tt>FractalClient<\/tt> object, passing in the name of the service endpoint I want it to connect to:\r\n   <\/p><pre>FractalClient fractal = new FractalClient(\"HttpBinding\");<\/pre><p>Since <tt>FractalClient<\/tt> implements the <tt>IFractal<\/tt> interface, the client program calls <tt>snowflake<\/tt> through the <tt>fractal<\/tt> object.\r\n   <\/p><pre>int[] bbox;\r\nint[][] outline = fractal.snowflake(out bbox, 4, width, height);<\/pre><p>And that's all there is to it. I didn't have to write any data marshalling code in either the client or the server.<\/p>\r\n   <p>Well, that's all there is to the data management. The client still has to draw the snowflake. <tt>snowflake<\/tt> returns an ordered list of vectors, the first of which starts at <tt>0,0<\/tt>. The algorithm is simple: draw a point at <tt>0,0<\/tt> and then a line to the end of the first vector. Make that endpoint the next origin, and repeat. MATLAB code:\r\n   <\/p><pre> point = zeros(1,2,class(vectors));\r\n rows = size(vectors, 1);\r\n for k = 1:rows\r\n      next = point + vectors(k,:);\r\n      line([point(1), next(1)], [point(2), next(2)]);\r\n      point = next;\r\n  end<\/pre><p>The C# code is only a little more verbose (see the example for details).<\/p>\r\n   <h3>Building and Running the Example<a name=\"5\"><\/a><\/h3>\r\n   <p>First, as usual, <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/31294-windows-communication-foundation-and-builder-ne-type-safe-apis\">download the code<\/a> from MATLAB Central.\r\n   <\/p>\r\n   <p>The download contains the MATLAB function <tt>snowflake.m<\/tt> and a Visual Studio 2008 solution <tt>Koch.sln<\/tt>. Create the server and client programs by following these four steps:\r\n   <\/p>\r\n   <li>Build the <tt>IFractal<\/tt> interface DLL.\r\n   <\/li>\r\n   <li>Create the <tt>Snowflake<\/tt> .NET assembly and the <tt>KochIFractal<\/tt> type safe interface.\r\n   <\/li>\r\n   <li>Compile the server program, <tt>KochServer<\/tt>, after referencing <tt>IFractal<\/tt> and <tt>KochIFractal<\/tt> in the <tt>KochServer<\/tt> project.\r\n   <\/li>\r\n   <li>Compile the client program, <tt>KochClient<\/tt>, which does not need references to any of the server assemblies.\r\n   <\/li>\r\n   <p>The file <tt>ReadmeWCF.txt<\/tt> contains detailed instructions.\r\n   <\/p>\r\n   <p>Then, open a separate DOS window for the server and the client. The server program requires the runtime setup usual for a\r\n      MATLAB-based deployed .NET application (the MCR DLLs must be on your system <tt>PATH<\/tt>), but the client does not. The client is a native .NET application which WCF isolates completely from any dependencies on\r\n      server DLLs and data types.\r\n   <\/p>\r\n   <p>In the server DOS window, run <tt>Koch\\KochServer\\bin\\Debug\\KochServer.exe<\/tt>. When the service is ready, the server displays a short message:\r\n   <\/p><pre>Koch Snowflake Service started.\r\nPress any key to terminate service...<\/pre><p>In the client DOS window, run <tt>Koch\\KochClient\\bin\\Debug\\KochClient.exe<\/tt>. In a few moments, a window will appear, and the client will render the snowflake. You can resize the window and the snowflake\r\n      will grow or shrink accordingly. Each time the window size changes, the client requests a new outline from the server. The\r\n      outline consists of 768 2D vectors and the bounding box requires four scalars, so each resize pulls 1,540 integers from the\r\n      server.\r\n   <\/p>\r\n   <h3>WCF Support Enables New Kinds of Deployment<a name=\"6\"><\/a><\/h3>\r\n   <p>Clients of a MATLAB-based WCF service do not require the MCR. And even though the client in my example is a Windows application,\r\n      that's not a requirement either. By creating a WCF service from a set of MATLAB functions, you enable lightweight cross-platform\r\n      deployment. Your clients no longer need to install your application -- instead, they access it via the Web. Of course, you'll\r\n      need to keep the service up and running for them. But in some scenarios, hosting can significantly reduce the amount of work\r\n      required to deploy a MATLAB-based solution to a large number of users.\r\n   <\/p>\r\n   <p>Will you deploy MATLAB applications using WCF? Let us know what kind of services you'll be building and how you plan to host\r\n      them -- and, as always, please ask questions -- I'd love to know how you think we can improve these tools <a href=\"https:\/\/blogs.mathworks.com\/loren\/?p=285#respond\">here<\/a>.\r\n   <\/p><script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_45163bdf6fa04ccf96924969c6128244() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='45163bdf6fa04ccf96924969c6128244 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 45163bdf6fa04ccf96924969c6128244';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        author = 'Peter Webb';\r\n        copyright = 'Copyright 2011 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add author and copyright lines at the bottom if specified.\r\n        if ((author.length > 0) || (copyright.length > 0)) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (author.length > 0) {\r\n                d.writeln('% _' + author + '_');\r\n            }\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n      \r\n      d.title = title + ' (MATLAB code)';\r\n      d.close();\r\n      }   \r\n      \r\n-->\r\n<\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_45163bdf6fa04ccf96924969c6128244()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n            the MATLAB code \r\n            <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; 7.12<br><\/p>\r\n<\/div>\r\n<!--\r\n45163bdf6fa04ccf96924969c6128244 ##### SOURCE BEGIN #####\r\n%% Deploying MATLAB Functions as .NET Web Services \r\n% Guest blogger \r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/authors\/4660 \r\n% Peter Webb> returns with another in an \r\n% <https:\/\/blogs.mathworks.com\/loren\/category\/deployment\/ occasional \r\n% series> of postings about application deployment. \r\n\r\n%% Publishing a MATLAB Function as a Web Service\r\n% Imagine that I've written a great \r\n% <https:\/\/www.mathworks.com\/products\/matlab\/ MATLAB>\r\n% application and deployed it as a \r\n% <https:\/\/www.mathworks.com\/products\/netbuilder\/ .NET application>.\r\n% Lots of people use it, and now I've been asked to make it\r\n% available via the web. Since it has no GUI, I don't want to run it in a\r\n% browser. I'd like to publish it as a\r\n% <http:\/\/en.wikipedia.org\/wiki\/Web_service _web service_>\r\n% so remote clients can\r\n% take advantage of its computational prowess. But that means I'll have to\r\n% send MATLAB matrices back and forth across the network, a challenging\r\n% coding task. Deployed type safe APIs allow me to integrate seamlessly\r\n% with Microsoft's \r\n% <http:\/\/msdn.microsoft.com\/en-us\/netframework\/aa663324 Windows \r\n% Communication Foundation> (WCF), automating most \r\n% of that work for me.\r\n%\r\n% I'll demonstrate how this works with an application that consists of four\r\n% parts:\r\n% \r\n% # A WCF-enabled type safe API.\r\n% # A deployed MATLAB C# component implementing the type safe API.\r\n% # A server application that publishes the service to client applications.\r\n% # A client application that consumes the published service.\r\n\r\n%% WCF-Enabling a Type Safe API\r\n% My MATLAB program generates the outline of a simple fractal, the \r\n% <http:\/\/en.wikipedia.org\/wiki\/Koch_snowflake Koch\r\n% snowflake>, which consists entirely of straight lines. The program \r\n% exports a single function:\r\n%\r\n%  function [vectors, bbox] = snowflake(n, width, height)\r\n%\r\n% |snowflake| returns the |n|-th iteration of the outline as a series of \r\n% two-dimensional |vectors|, scaled to fit within a rectangle of |width| \r\n% by |height| units. The second output, |bbox|, specifies a rectangle that\r\n% fits tightly around the outline. \r\n%\r\n% From my C# client, I'd like to call |snowflake| with integer inputs and\r\n% outputs. The inputs are scalars, so I declare them as simple integers.\r\n% The first output, |vectors|, is a vector of vectors (a matrix!), while\r\n% the second, |bbox| is a 4-element vector. I declare my C# |snowflake|\r\n% function within a new interface, |IFractal|:\r\n%\r\n%  public interface IFractal\r\n%  {\r\n%    int[][] snowflake(out int[] bbox, int n, int width, int height);\r\n%  }\r\n%\r\n% Both C# and WCF support multi-dimensional arrays, but WCF requires \r\n% the _jagged_ array storage format. As a result, I declare \r\n% |snowflake|'s return value |int[][]| (a jagged array) instead of C#'s \r\n% more efficient |int[,]|. \r\n%\r\n% I need to make two more changes to web-enable this type safe API: I\r\n% decorate both the interface and the function with WCF-specific \r\n% <http:\/\/msdn.microsoft.com\/en-us\/library\/z0w1kczw%28v=vs.80%29.aspx \r\n% _attributes_> asserting that the function provides an\r\n% <http:\/\/msdn.microsoft.com\/en-us\/library\/system.servicemodel.operationcontractattribute.aspx\r\n% _operation_> as part of a web \r\n% <http:\/\/msdn.microsoft.com\/en-us\/library\/system.servicemodel.servicecontractattribute.aspx \r\n% _service_>.\r\n%\r\n%  [ServiceContract]\r\n%  public interface IFractal\r\n%  {\r\n%      [OperationContract(Name = \"snowflake\")]\r\n%      int[][] snowflake(out int[] bbox, int n, int width, int height);\r\n%  }\r\n%\r\n% If your service interface exposes overloaded functions as operations, \r\n% you must give each a unique |Name|.\r\n\r\n%% A MATLAB-based WCF Server\r\n% A WCF service needs a _host_, a server program that listens for and \r\n% responds to client requests. Each request asks the server to perform an\r\n% operation defined by a service contract based on a WCF-enabled \r\n% .NET interface. My server hosts a single service,\r\n% |Snowflake.KochIFractal|, based on the |IFractal| interface.\r\n%\r\n% I create my |snowflake| server, |KochServer|, in three steps:\r\n%\r\n% # Deploy |snowflake| into a .NET assembly implementing a type safe API\r\n% based on |IFractal|.\r\n% # Define a service named |Snowflake.KochIFractal| that exposes the\r\n% |IFractal| interface.\r\n% # Create a .NET |ServiceHost| object that hosts the\r\n% |Snowflake.KochIFractal| service.\r\n%\r\n% The first step is easy: I create deploytool project using Builder NE and\r\n% generate a type safe API using |IFractal|. (I covered this process in\r\n% detail in my first type safe API post.)\r\n%\r\n% The second and third steps require a little knowledge of WCF servers. \r\n% The simplest type of servers\r\n% (<http:\/\/msdn.microsoft.com\/en-us\/library\/bb332338.aspx self-hosted>) \r\n% consist of a \r\n% <http:\/\/msdn.microsoft.com\/en-us\/library\/ms731734.aspx  WCF service \r\n% configuration file> and a managed .NET \r\n% application. The configuration file defines the services hosted by the \r\n% managed application. \r\n%\r\n% The configuration file describes each service and its behaviors, \r\n% identifying _endpoints_ from which clients can request operations. \r\n% For example, |KochServer|'s configuration file, |App.config|, exposes the\r\n% |IFractal| interface through an endpoint named |HttpBinding|. \r\n%\r\n%  <endpoint\r\n%       address=\"\"\r\n%       binding=\"wsHttpBinding\"\r\n%       bindingConfiguration=\"wsHttpConfig\"\r\n%       contract=\"IFractal\"\r\n%       name=\"HttpBinding\" \/>\r\n%\r\n% I derived |KochServer|'s configuration file from the configuration file\r\n% that ships with the WCF example. You can do the same; just\r\n% make sure to edit the configuration file to reflect the name of your\r\n% service and your endpoint |contract|.\r\n%\r\n% The managed application, the host program itself, can be as simple as a\r\n% .NET console application. Create a conole application project, add the\r\n% configuration file to the project and then, in your |Main| function,\r\n% create a |ServiceHost| object for your service. |KochServer| creates a\r\n% |ServiceHost| for |Snowflake.KochIFractal|, the service defined in\r\n% |KochServer|'s configuration file.\r\n%\r\n%  ServiceHost host = new ServiceHost(typeof(Snowflake.KochIFractal))\r\n% \r\n% A self-hosted service must start and stop the service somehow.\r\n% |KochServer| starts the service when the server program starts and then\r\n% waits for the user to press a key; the first keystroke stops the service.\r\n% Your services will probably start and stop using more sophisticated\r\n% mechanisms.\r\n\r\n%% A C# Client Program\r\n% The client program renders the Koch snowflake into a Windows form with\r\n% the native .NET drawing API (the\r\n% <http:\/\/msdn.microsoft.com\/en-us\/library\/system.drawing.aspx\r\n% System.Drawing namespace>). Like the server, the client is a standard\r\n% .NET console application. The client interacts with the server via a\r\n% <http:\/\/msdn.microsoft.com\/en-us\/library\/ms730144%28v=VS.90%29.aspx \r\n% _proxy_>, an object that manages the actual network connection to the\r\n% |KochServer|. Since writing a proxy is an exercise in boiler-plate\r\n% tedium, Microsoft provides a tool, \r\n% <http:\/\/msdn.microsoft.com\/en-us\/library\/aa347733%28v=VS.90%29.aspx \r\n% |svcutil.exe|>, that automatically\r\n% generates proxies from services. I started |KochServer|, then ran this \r\n% |svcutil| command:\r\n%\r\n%   svcutil \/t:code http:\/\/localhost:8001\/KochServer\/ \r\n%           \/out:FractalClient.cs \/config:App.config\r\n%\r\n% |svcutil| generated a C# proxy class, |FractalClient|, and a configuration\r\n% file, |App.config|, for my client program. I added both of these files to\r\n% my |KochClient| Visual Studio project.  \r\n%\r\n% In my client's |Main| method, I create a |FractalClient| object, passing\r\n% in the name of the service endpoint I want it to connect to:\r\n%\r\n%  FractalClient fractal = new FractalClient(\"HttpBinding\");\r\n% \r\n% Since |FractalClient| implements the |IFractal| interface, the client\r\n% program calls |snowflake| through the |fractal| object.\r\n%\r\n%  int[] bbox;\r\n%  int[][] outline = fractal.snowflake(out bbox, 4, width, height);\r\n%\r\n% And that's all there is to it. I didn't have to write any data\r\n% marshalling code in either the client or the server.  \r\n%\r\n% Well, that's all there is to the data management. The client still has to\r\n% draw the snowflake. |snowflake| returns an ordered list of vectors, the\r\n% first of which starts at |0,0|. The algorithm is simple: draw a point at\r\n% |0,0| and then a line to the end of the first vector. Make that endpoint\r\n% the next origin, and repeat. MATLAB code:\r\n%\r\n%   point = zeros(1,2,class(vectors));\r\n%   rows = size(vectors, 1);\r\n%   for k = 1:rows\r\n%        next = point + vectors(k,:);\r\n%        line([point(1), next(1)], [point(2), next(2)]);\r\n%        point = next;\r\n%    end\r\n%\r\n% The C# code is only a little more verbose (see the example for details).\r\n\r\n%% Building and Running the Example\r\n% First, as usual, \r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/31294-windows-communication-foundation-and-builder-ne-type-safe-apis \r\n% download the code> from MATLAB Central.\r\n%\r\n% The download contains the MATLAB function |snowflake.m| and a Visual\r\n% Studio 2008 solution |Koch.sln|. Create the server and client programs by\r\n% following these four steps:\r\n%\r\n% # Build the |IFractal| interface DLL.\r\n% # Create the |Snowflake| .NET assembly and the |KochIFractal| type\r\n% safe interface.\r\n% # Compile the server program, |KochServer|, after referencing |IFractal| and\r\n% |KochIFractal| in the |KochServer| project.\r\n% # Compile the client program, |KochClient|, which does not need\r\n% references to any of the server assemblies.\r\n%\r\n% The file |ReadmeWCF.txt| contains detailed instructions.\r\n%\r\n% Then, open a separate DOS window for the server and the client. The\r\n% server program requires the runtime setup usual for a MATLAB-based\r\n% deployed .NET application (the MCR DLLs must be on your system |PATH|), \r\n% but the client does not. The client is a native .NET application which WCF\r\n% isolates completely from any dependencies on server DLLs and data types.\r\n%\r\n% In the server DOS window, run |Koch\\KochServer\\bin\\Debug\\KochServer.exe|.\r\n% When the service is ready, the server displays a short message:\r\n%\r\n%  Koch Snowflake Service started.\r\n%  Press any key to terminate service...\r\n%\r\n% In the client DOS window, run |Koch\\KochClient\\bin\\Debug\\KochClient.exe|.\r\n% In a few moments, a window will appear, and the client will render the\r\n% snowflake. You can resize the window and the snowflake will grow or\r\n% shrink accordingly. Each time the window size changes, the client\r\n% requests a new outline from the server. The outline consists of 768 2D\r\n% vectors and the bounding box requires four scalars, so each resize pulls \r\n% 1,540 integers from the server.\r\n\r\n%% WCF Support Enables New Kinds of Deployment\r\n% Clients of a MATLAB-based WCF service do not require the MCR. And even\r\n% though the client in my example is a Windows application, that's not a\r\n% requirement either. By creating a WCF service from a set of \r\n% MATLAB functions, you enable lightweight cross-platform deployment. Your\r\n% clients no longer need to install your application REPLACE_WITH_DASH_DASH instead, they\r\n% access it via the Web. Of course, you'll need to keep the service up and\r\n% running for them. But in some scenarios, hosting can\r\n% significantly reduce the amount of work required to deploy a MATLAB-based\r\n% solution to a large number of users.\r\n% \r\n% Will you deploy MATLAB applications using WCF? Let us know what kind of\r\n% services you'll be building and how you plan to host them REPLACE_WITH_DASH_DASH and, as\r\n% always, please ask questions REPLACE_WITH_DASH_DASH I'd love to know how you think we can\r\n% improve these tools <https:\/\/blogs.mathworks.com\/loren\/?p=285#respond\r\n% here>.\r\n\r\n##### SOURCE END ##### 45163bdf6fa04ccf96924969c6128244\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   \r\n      Guest blogger Peter Webb returns with another in an occasional series of postings about application deployment.\r\n      \r\n   \r\n   Contents\r\n   \r\n      \r\n   ... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/loren\/2011\/08\/17\/builder-ne-and-the-windows-communication-foundation\/\">read more >><\/a><\/p>","protected":false},"author":39,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[24],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/285"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/users\/39"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/comments?post=285"}],"version-history":[{"count":0,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/285\/revisions"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/media?parent=285"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/categories?post=285"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/tags?post=285"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}