dot_net_services 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,282 @@
1
+ require 'uri'
2
+ require 'cgi'
3
+ require 'net/http'
4
+
5
+ module DotNetServices
6
+
7
+ # The Session class is used for communicating with endpoints of .NET Services bus.
8
+ #
9
+ # == Usage examples
10
+ #
11
+ # A Session instance represents a .NET Services bus endpoint. Typically, you create it by calling Session#open
12
+ # and then exchange HTTP messages using methods like #get, #post, etc. It looks like this:
13
+ #
14
+ # Send a GET with no parameters:
15
+ #
16
+ # session = Session.open('/MySolution/MyService', :username => 'MySolution', :password => 'my_password')
17
+ # get_response = session.get
18
+ # # ... process response, which is a Net::HTTP::Response instance
19
+ #
20
+ # Send a GET with ?age=21&sex=Male query string:
21
+ #
22
+ # get_with_query_response = session.get :age => 21, :sex => "Male"
23
+ #
24
+ # Send a POST with name=Joe&email=joe@the_plumber.com (URL-encoded form) as a body:
25
+ #
26
+ # post_response = session.post :name => 'Joe', :email => 'joe@the_plumber.com'
27
+ #
28
+ # So far, Session API is similar to Net::HTTP::Session. Which is the whole point of the REST style
29
+ # communication - it is all just HTTP! However, there is one small twist. HTTP::Session represents a server
30
+ # (host and port). DotNetServices::Session represents a service endpoint. Which is a <b>URL</b>, not a server. In
31
+ # fact, all .NET Services endpoints have the same server, servicebus.windows.net. So an endpoint address is really
32
+ # just a path on that server.
33
+ #
34
+ # And sometimes you need to send requests to a path under the endpoint. For example, to update the name of customer
35
+ # #12345, you would do a POST to /MySolution/Customer/12345 with &name=Dave body. Creating a new Session for that is
36
+ # both counterintuitive and expensive (see the Details section below). For this reason, DotNetServices::Session has
37
+ # methods like post_to_url:
38
+ #
39
+ # result = session.post_to_url(12345, :name => 'Dave')
40
+ #
41
+ # == Details
42
+ #
43
+ # When a session is created, it's given the URL of an endpoint (that looks like /SolutionName/path/to/service), and
44
+ # username / password. These are <b>solution's</b> username and password, needed to prove to the bus that
45
+ # your consumer is a part of this solution. If the solution allows anonymous access, username / password are not
46
+ # necessary.
47
+ #
48
+ # When a session is opened (or is asked to send a first request to the endpoint), the session authenticates itself
49
+ # to the .NET Services using Identity Service [http://accesscontrol.windows.net], and obtains a security token from it.
50
+ #
51
+ # Security token is a Base64-encoded string. Unless an endpoint allows unauthenticated access, any request that comes
52
+ # to the endpoint must have this security token attached to it (as X-MS-Identity-Token HTTP header).
53
+ # DotNetServices::Session takes care of this responsibility, as well as renewing stale tokens.
54
+ #
55
+ # Session also has methods get_from_relay and post_to_relay, that are used for communicating to the .NET Services
56
+ # bus management endpoint. These methods (createmb, retrieve, query) are used by MessageBuffer, an application normally
57
+ # shouldn't need to use them directly.
58
+ #
59
+ # == Guidelines
60
+ #
61
+ # Obtaining a security token is an expensive operation, so it is <b>not</b> recommended to create a new instance of
62
+ # a Session for every outgoing request to the endpoint. It's better to use one Session instance per endpoint.
63
+ # Session takes care of expiring security tokens autoimatically, so Session instances don't go stale even after long
64
+ # periods of inactivity.
65
+ class Session
66
+
67
+ attr_reader :authenticator
68
+
69
+ class << self
70
+ # Open a .Net Services session at the +endpoint+.
71
+ #
72
+ # If +auth_data+ is provided, authenticates the session with
73
+ # the identity service using it. In this version, +auth_data+ should be a hash containing +:username+ and
74
+ # +:password+ keys. Other authentication mechanisms (InformationCard, X.509 certificates etc) that the Identity
75
+ # service provides are not exposed via a REST interface, therefore are not available to this library.
76
+ #
77
+ # If #open is called with a block, it passes the session instance as an argument to the block and returns the
78
+ # result of the block. If there is no block, session instance is returned instead.
79
+ def open(endpoint, auth_data = nil, &block)
80
+ Session.new(endpoint, auth_data).open(&block)
81
+ end
82
+ end
83
+
84
+ # Initialize a new .NET Session at the +endpoint+.
85
+ #
86
+ # If +auth_data+ is provided, remember it. Acquiring
87
+ # authentication token is postponed until it's needed.
88
+ def initialize(endpoint, auth_data=nil)
89
+ @endpoint_uri = setup_endpoint(endpoint)
90
+ @authenticator = Authentication.setup(auth_data)
91
+ end
92
+
93
+ # See DotNetServices::Session.open.
94
+ def open
95
+ authenticate
96
+ block_given? ? yield(self) : self
97
+ end
98
+
99
+ # Acquire a security token from the Identity Service.
100
+ #
101
+ # This method will do nothing if:
102
+ # * this session already holds a security token and the token has not expired yet, or
103
+ # * the session was created without auth_data (anonymous session)
104
+ def authenticate
105
+ @authenticator.authenticate
106
+ end
107
+
108
+ # Send a GET request to the .NET Services endpoint.
109
+ #
110
+ # If query options are provided, they should be a hash, and they are converted to a query string and attached to
111
+ # the GET request target URL.
112
+ # Thus, session.get(:foo => 'bar') sends a GET to #{endpoint}?foo=bar
113
+ def get(query_options=nil)
114
+ get_from_url(nil, query_options)
115
+ end
116
+
117
+
118
+ def get_from_url(url, query_options=nil)
119
+ uri = setup_query_string(url, query_options)
120
+ get_request = Net::HTTP::Get.new(uri.request_uri)
121
+ enhance_and_execute(get_request)
122
+ end
123
+
124
+ # Sends a GET to the service management endpoint.
125
+ #
126
+ # This is used by MessageBuffer for VMB management. Applications shouldn't need to use this method.
127
+ def get_from_relay(query_options=nil)
128
+ uri = setup_query_string(nil, query_options)
129
+ get_request = Net::HTTP::Get.new(uri.request_uri)
130
+ route_to_relay(get_request)
131
+ enhance_and_execute(get_request)
132
+ end
133
+
134
+ # Send a POST request to the .NET Services endpoint.
135
+ #
136
+ # If +data+ is a Hash it is converted to a URL-encoded form, otherwise it is placed in the post body without any
137
+ # conversion.
138
+ #
139
+ # +content_type+ by default is set to +application/x-www-form-urlencoded+, which is appropriate when +data+ is a
140
+ # Hash. In any other case, you should specify +content_type+ explicitly.
141
+ def post(data=nil, content_type='application/x-www-form-urlencoded')
142
+ post_to_url("", data, content_type)
143
+ end
144
+
145
+ # Sends a POST request to a path below .NET Services endpoint.
146
+ #
147
+ # If an application neeeds to send a POST to a service that uses URL to receive data, it should use this method
148
+ # instead of creating a new session for every new request. For example, if a service endpoint is called
149
+ # /Solution/Maps, and it's URL template is /Solution/Maps/*country*/*province*/*city*, a way to create a map of
150
+ # Calgary would be:
151
+ #
152
+ # session.post_to_url('/Canada/Calgary', map_data, content_type=...)
153
+ def post_to_url(url, data=nil, content_type='application/x-www-form-urlencoded')
154
+ post_request = Net::HTTP::Post.new(@endpoint_uri.path + url.to_s)
155
+ if data
156
+ post_request.content_type = content_type
157
+ if content_type == 'application/x-www-form-urlencoded'
158
+ post_request.form_data = data
159
+ else
160
+ post_request.body = data
161
+ end
162
+ end
163
+ enhance_and_execute(post_request)
164
+ end
165
+
166
+
167
+ # Sends a POST to the service management endpoint.
168
+ #
169
+ # This is used by MessageBuffer for VMB management. Applications should use MessageBuffer#keep_alive.
170
+ def post_to_relay(data=nil, content_type='application/x-www-form-urlencoded')
171
+ post_request = Net::HTTP::Post.new(@endpoint_uri.path)
172
+
173
+ if data
174
+ post_request.content_type = content_type
175
+ if content_type == 'application/x-www-form-urlencoded'
176
+ post_request.form_data = data
177
+ else
178
+ post_request.body = data
179
+ end
180
+ end
181
+ route_to_relay(post_request)
182
+ enhance_and_execute(post_request)
183
+ end
184
+
185
+ # Create a new message buffer (sends an X-CREATEMB to the service management endpoint).
186
+ #
187
+ # This is used by MessageBuffer for VMB management. Applications should use MessageBuffer#open.
188
+ def createmb
189
+ request = Net::HTTP::CreateMB.new(@endpoint_uri.path)
190
+ route_to_relay(request)
191
+ enhance_and_execute(request)
192
+ end
193
+
194
+ # Subscribe a message buffer to a virtual endpoint (sends an X-SUBSCRIBE to the VMB management endpoint).
195
+ #
196
+ # This is used by MessageBuffer for VMB management. Applications should use MessageBuffer#open.
197
+ def subscribe(request_options)
198
+ uri = setup_query_string(nil, request_options)
199
+ request = Net::HTTP::Subscribe.new(uri.request_uri)
200
+ route_to_relay(request)
201
+ enhance_and_execute(request)
202
+ end
203
+
204
+ # Unsubscribe a message buffer from a virtual endpoint (sends an X-UNSUBSCRIBE to the VMB management endpoint).
205
+ #
206
+ # This is used by MessageBuffer for VMB management. Applications should use MessageBuffer#open.
207
+ def unsubscribe(request_options)
208
+ uri = setup_query_string(nil, request_options)
209
+ request = Net::HTTP::Unsubscribe.new(uri.request_uri)
210
+ route_to_relay(request)
211
+ enhance_and_execute(request)
212
+ end
213
+
214
+ # Retrieve the next message from the message buffer (sends an X-RETRIEVE to the service management endpoint).
215
+ #
216
+ # This is used by MessageBuffer for VMB management. Applications should use MessageBuffer#poll.
217
+ def retrieve(query_options={})
218
+ query_options = stringify_and_downcase_keys(query_options)
219
+ query_options['timeout'] ||= 15
220
+ uri = setup_query_string(nil, query_options)
221
+ request = Net::HTTP::Retrieve.new(uri.request_uri)
222
+ route_to_relay(request)
223
+ enhance_and_execute(request)
224
+ end
225
+
226
+
227
+ # Delete an endpoint (sends a DELETE to the service management endpoint).
228
+ #
229
+ # This is used by MessageBuffer for VMB management. Applications should use MessageBuffer#delete.
230
+ def delete
231
+ request = Net::HTTP::Delete.new(@endpoint_uri.path)
232
+ route_to_relay(request)
233
+ enhance_and_execute(request)
234
+ end
235
+
236
+ # The URL of a .NET services endpoint this Session is connected to.
237
+ def endpoint
238
+ @endpoint_uri.to_s
239
+ end
240
+
241
+ private
242
+
243
+ def enhance_and_execute(request)
244
+ @authenticator.enhance(request)
245
+ DotNetServices.proxy.start(@endpoint_uri.host, @endpoint_uri.port) { |http| http.request(request) }
246
+ end
247
+
248
+ def route_to_relay(request)
249
+ request['X-Process-At'] = 'http://schemas.microsoft.com/ws/2007/08/connect/roles/relay'
250
+ end
251
+
252
+ def setup_endpoint(endpoint)
253
+ if endpoint !~ /^http(s?):\/\//
254
+ endpoint = '/' + endpoint unless endpoint[0] == ?/
255
+ endpoint = DotNetServices.root_url + endpoint
256
+ end
257
+ endpoint += '/' unless endpoint[-1] == ?/
258
+ URI.parse(endpoint)
259
+ end
260
+
261
+ def setup_query_string(url, query_options)
262
+ if url && !url.empty?
263
+ uri = @endpoint_uri + url.to_s
264
+ else
265
+ uri = @endpoint_uri.dup
266
+ end
267
+
268
+ if query_options
269
+ query = query_options.map { |k, v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" }.join('&')
270
+ uri.query = query
271
+ end
272
+ uri
273
+ end
274
+
275
+ def stringify_and_downcase_keys(options)
276
+ new_options = {}
277
+ options.each { |key, value| new_options[key.to_s.downcase] = value unless value.nil? }
278
+ new_options
279
+ end
280
+
281
+ end
282
+ end
@@ -0,0 +1,143 @@
1
+ require 'dot_net_services/session'
2
+ require 'dot_net_services/authentication'
3
+ require 'dot_net_services/error'
4
+ require 'dot_net_services/message_buffer'
5
+ require 'net/http/create_mb'
6
+ require 'net/http/retrieve'
7
+ require 'net/http/subscribe'
8
+
9
+ # DotNetServices is the top-level namespace of <b>.NET Services for Ruby</b>, Ruby interoperability layer for
10
+ # .NET Services plain HTTP (REST) API.
11
+ #
12
+ # == .NET Services
13
+ #
14
+ # Since you are reading this, you probably already know that .NET Services is a Microsoft product, described as the
15
+ # "Internet Services Bus", a messaging bus in the cloud. Like any other messaging bus, it helps services and consumers
16
+ # to communicate with each other. Further information on .NET Services can be found on MSDN:
17
+ # http://go.microsoft.com/fwlink/?LinkID=129428.
18
+ #
19
+ # While .NET Services primarily target .NET platform, non-Microsoft software is also catered for,
20
+ # by providing open protocols for most of the bus functionality, in both SOAP/WS-* and plain HTTP style. The latter
21
+ # is structured in a way that makes it easy to implement REST interactions over the bus, including both
22
+ # synchronous and asynchronous semantics. .NET Services bus doesn't force an application to use REST, any
23
+ # other kind of plain HTTP protocol can be routed through it, too.
24
+ #
25
+ #
26
+ # == Functionality
27
+ #
28
+ # This library is a simple Ruby wrapper for .NET Services plain HTPP (REST) APIs. Current version allows Ruby
29
+ # developers to build consumers of synchronous RESTful services (implemented as .NET WCF services, using
30
+ # webHttpRelayBinding, provided by the .NET Services SDK). You can also exchange messages between Ruby processes via
31
+ # Volatile Message Buffers (VMBs), which are .NET Services mechanism for asynchronous communications.
32
+ #
33
+ # .NET Services for Ruby looks like Net::HTTP API from the standard library, but deals with authentication,
34
+ # VMB management and message retrieval.
35
+ #
36
+ # Since this is a 0.1.0 version of an interoperability layer for a PDC version of a bus, a few things are missing.
37
+ #
38
+ # Most notably, with this version you still can not:
39
+ # * communicate with WCF services bound by anything other than webHttpRelayBinding.
40
+ # * communicate with the bus via WS-* protocols.
41
+ # * communicate with a WCF-based service via a VMB. At least, not until .NET Services SDK adds a WCF binding for
42
+ # REST via VMB. Once it's available, we should be able to work with it.
43
+ # * use VMB pub-sub and multicast functionality
44
+ # * use Workflow Services
45
+ # * use Identity Service as a dfederated identity provider for end-users
46
+ #
47
+ # == Usage examples
48
+ #
49
+ # Say, you are a cellphone dealer. You have a Point of Sale web application, written in Rails. It sells cellphones.
50
+ # The phones you sell are operated by a phone company, which offers a .NET Services solution (group of services in
51
+ # the .NET Services world), called Dealership. It includes two services, Customer and Provisioning.
52
+ #
53
+ # Customer service is a RESTful service endpoint, implemented by WCF service with a webHttpRelayBinding. It's listening
54
+ # on /Customer URL, and provides the usual CRUD functionality for managing customers.
55
+ #
56
+ # Provisioning service endpoint is a VMB. Coincidentally, it's also written in Ruby! :) When a customer buys a new phone,
57
+ # provisioning application should activate the phohe on the network, so that the customer can actually make calls with it.
58
+ # Activation can take several minutes, even hours, and we don't want the point of sale terminal to hang until it's over.
59
+ # Hence the use of a VMB as an asynchronous communication device.
60
+ #
61
+ # To create a customer, point of sale app needs to post a URL-encoded form to a webHttpRelayBinding endpoint. That's
62
+ # where you need to use a DotNetServices::Session class:
63
+ #
64
+ # require 'dotnetservices'
65
+ # session = DotNetServices::Session.open("/Dealership/Customer", :username => 'Dealership', :password => '_password')
66
+ # session.post :first_name => 'John', :last_name => 'Doe'
67
+ #
68
+ # Posting a message to a Provisioning endpoint would actually look the same:
69
+ #
70
+ # session = DotNetServices::Session.open("/Dealership/Provisioning", :username => 'Dealership', :password => '_password')
71
+ # session.post :phone_number => '555 888-8888'
72
+ #
73
+ # DotNetServices::MessageBuffer is needed by the Provisioning *service* (and not the client), to register the VMB and
74
+ # retrieve messages from it. Usage typically looks like this:
75
+ #
76
+ # buffer = DotNetServices::MessageBuffer.new("/Dealership/Provisioning",
77
+ # :username => 'Dealership', :password => '_password')
78
+ # buffer.open_and_poll do |message|
79
+ # ... process incoming messages ...
80
+ # end
81
+ #
82
+ # This code will check that the VMB exists, create one if necessary, and continuously poll it for new messages. Whenever
83
+ # a new message is sent to VMB, MessageBuffer#open_and_poll retrieves it and invokesthe block, passing it a
84
+ # Net::HTTP::Request instance that looks exactly like what the sender originally sent to the VMB. Nice and easy.
85
+ #
86
+ # To understand and use .NET Services for Ruby, you should probably also read the documentation for the two classes
87
+ # mentioned above: DotNetServices::Session and DotNetServices::MessageBuffer.
88
+ #
89
+ # Happy bussing!
90
+ module DotNetServices
91
+
92
+ class << self
93
+
94
+ # The name of the host providing DotNetServices relay services.
95
+ def relay_host
96
+ "servicebus.windows.net"
97
+ end
98
+
99
+ # The name of the host providing DotNetServices identity services.
100
+ def identity_host
101
+ 'accesscontrol.windows.net'
102
+ end
103
+
104
+ # The root URL used for exposing services.
105
+ def root_url
106
+ "http://#{relay_host}/services"
107
+ end
108
+
109
+ # Host and port of the bus endpoint.
110
+ def host_port
111
+ return @host_port if @host_port
112
+ uri = URI.parse(root_url)
113
+ @host_port = [uri.host, uri.port]
114
+ @host_port
115
+ end
116
+
117
+ # Use an HTTP proxy to connect to .NET Services
118
+ #
119
+ # If you call this method, all subsequent communications with .NET Services will use an HTTP proxy.
120
+ # You must given hostname and password #use proxy
121
+ # DotNetServices.use_proxy()
122
+ def use_proxy(proxy_host, proxy_port, proxy_user = nil, proxy_password = nil)
123
+ @proxy = Net::HTTP::Proxy(proxy_host, proxy_port, proxy_user, proxy_password)
124
+ end
125
+
126
+ # An HTTP proxy to connect through.
127
+ #
128
+ # Defaults to Net::HTTP (direct connection without proxy). To set a proxy, see #use_proxy.
129
+ def proxy
130
+ @proxy || Net::HTTP
131
+ end
132
+
133
+ # TODO implement!
134
+ def logger
135
+ if RAILS_ENV
136
+ nil
137
+ else
138
+ @logger ||= nil
139
+ end
140
+ end
141
+
142
+ end
143
+ end
@@ -0,0 +1,14 @@
1
+ module Net # :nodoc:
2
+ class HTTP # :nodoc:
3
+ # Custom request type X-CREATEMB for creating message buffers on
4
+ # the .NET Service Bus.
5
+ #
6
+ # This request should not be used directly. Use
7
+ # DotNetServices::Session#createmb instead.
8
+ class CreateMB < HTTPRequest
9
+ METHOD = "X-CREATEMB"
10
+ REQUEST_HAS_BODY = false
11
+ RESPONSE_HAS_BODY = true
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Net # :nodoc:
2
+ class HTTP # :nodoc:
3
+ # Custom X-RETRIEVE for retrieving messages from the .NET Services
4
+ # message buffer.
5
+ #
6
+ # This request should not be used directly. Use
7
+ # DotNetServices::Session#retrieve instead.
8
+ class Retrieve < HTTPRequest
9
+ METHOD = "X-RETRIEVE"
10
+ REQUEST_HAS_BODY = false
11
+ RESPONSE_HAS_BODY = true
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Net # :nodoc:
2
+ class HTTP # :nodoc:
3
+ # Custom request type X-CREATEMB for creating message buffers on
4
+ # the .NET Service Bus.
5
+ #
6
+ # This request should not be used directly. Use
7
+ # DotNetServices::Session#createmb instead.
8
+ class Subscribe < HTTPRequest
9
+ METHOD = "X-SUBSCRIBE"
10
+ REQUEST_HAS_BODY = false
11
+ RESPONSE_HAS_BODY = true
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module Net # :nodoc:
2
+ class HTTP # :nodoc:
3
+ # Custom request type X-CREATEMB for creating message buffers on
4
+ # the .NET Service Bus.
5
+ #
6
+ # This request should not be used directly. Use
7
+ # DotNetServices::Session#createmb instead.
8
+ class Unsubscribe < HTTPRequest
9
+ METHOD = "X-UNSUBSCRIBE"
10
+ REQUEST_HAS_BODY = false
11
+ RESPONSE_HAS_BODY = true
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ namespace DotNetServicesRuby
2
+ {
3
+ using System.ServiceModel;
4
+
5
+ [ServiceBehavior(Name = "SyndicationService", Namespace = "http://samples.microsoft.com/ServiceModel/Relay/")]
6
+ class AnonymousResourceService : ResourceService
7
+ {
8
+ }
9
+ }
@@ -0,0 +1,32 @@
1
+ <?xml version="1.0" encoding="utf-8" ?>
2
+ <configuration>
3
+ <system.serviceModel>
4
+
5
+ <bindings>
6
+ <!-- Application Binding -->
7
+ <webHttpRelayBinding>
8
+ <binding name="default" />
9
+ </webHttpRelayBinding>
10
+ </bindings>
11
+
12
+ <services>
13
+ <!-- Application Service -->
14
+ <service name="DotNetServicesRuby.ResourceService"
15
+ behaviorConfiguration="default">
16
+ <endpoint contract="DotNetServicesRuby.ResourceContract"
17
+ binding="webHttpRelayBinding"
18
+ bindingConfiguration="default"
19
+ address="" />
20
+ </service>
21
+ </services>
22
+
23
+ <behaviors>
24
+ <serviceBehaviors>
25
+ <behavior name="default">
26
+ <serviceDebug httpHelpPageEnabled="false" httpsHelpPageEnabled="false" />
27
+ </behavior>
28
+ </serviceBehaviors>
29
+ </behaviors>
30
+
31
+ </system.serviceModel>
32
+ </configuration>
@@ -0,0 +1,37 @@
1
+ namespace DotNetServicesRuby
2
+ {
3
+ using System;
4
+ using System.Runtime.Serialization;
5
+ using System.ServiceModel;
6
+ using System.ServiceModel.Web;
7
+ using System.ServiceModel.Channels;
8
+
9
+ [ServiceContract]
10
+ [ServiceBehavior]
11
+ class PlainTextService
12
+ {
13
+ [OperationContract(Action="*", ReplyAction="*")]
14
+ [WebInvoke(BodyStyle=WebMessageBodyStyle.Bare)]
15
+ //public string Process(string foo)
16
+ //{
17
+ // return "hi mom";
18
+ //}
19
+
20
+ public Message Process(Message message)
21
+ {
22
+ var httpRequest = (HttpRequestMessageProperty)(message.Properties["httpRequest"]);
23
+
24
+ var query = httpRequest.QueryString;
25
+ var verb = httpRequest.Method;
26
+ var body = "";
27
+
28
+ Message response = Message.CreateMessage(MessageVersion.None, "GETRESPONSE", "hi, mom");
29
+
30
+ HttpResponseMessageProperty responseProperty = new HttpResponseMessageProperty();
31
+ responseProperty.Headers.Add("Content-Type", "text/plain");
32
+ response.Properties.Add(HttpResponseMessageProperty.Name, responseProperty);
33
+ return response;
34
+ }
35
+
36
+ }
37
+ }
@@ -0,0 +1,49 @@
1
+ namespace DotNetServicesRuby
2
+ {
3
+ using System;
4
+ using System.ServiceModel;
5
+ using System.ServiceModel.Web;
6
+ using System.ServiceModel.Description;
7
+ using Microsoft.ServiceBus;
8
+
9
+ class Program
10
+ {
11
+ static void Main(string[] args)
12
+ {
13
+
14
+ System.Console.WriteLine("Enter solution name: ");
15
+ var solutionName = System.Console.ReadLine();
16
+ System.Console.WriteLine("Enter password for " + solutionName + " solution:");
17
+ var password = System.Console.ReadLine();
18
+
19
+ var behavior = new TransportClientEndpointBehavior();
20
+ behavior.CredentialType = TransportClientCredentialType.UserNamePassword;
21
+ behavior.Credentials.UserName.UserName = solutionName;
22
+ behavior.Credentials.UserName.Password = password;
23
+
24
+ var address = new Uri(String.Format("http://{0}/services/{1}/TestService/", ServiceBusEnvironment.DefaultRelayHostName, solutionName));
25
+ var host = new ServiceHost(typeof(ResourceService), address);
26
+ host.Description.Endpoints[0].Behaviors.Add(behavior);
27
+ host.Open();
28
+
29
+ //var anonymousAddress = new Uri(String.Format("http://{0}/services/{1}/AnonymousTestService/", ServiceBusEnvironment.DefaultRelayHostName, solutionName));
30
+ //var anonymousHost = new ServiceHost(typeof(AnonymousResourceService), anonymousAddress);
31
+ //anonymousHost.Description.Endpoints[0].Behaviors.Add(behavior);
32
+ //anonymousHost.Open();
33
+
34
+ //var plainTextAddress = new Uri(String.Format("http://{0}/services/{1}/PlainTextTestService/", ServiceBusEnvironment.DefaultRelayHostName, solutionName));
35
+ //var plainTextHost = new WebServiceHost(typeof(PlainTextService), plainTextAddress);
36
+ //plainTextHost.Description.Endpoints[0].Behaviors.Add(behavior);
37
+ //plainTextHost.Open();
38
+
39
+ Console.WriteLine("Service address: " + address);
40
+ Console.WriteLine("Press [Enter] to exit");
41
+ Console.ReadLine();
42
+
43
+ host.Close();
44
+ //anonymousHost.Close();
45
+ //plainTextHost.Close();
46
+ }
47
+
48
+ }
49
+ }
@@ -0,0 +1,33 @@
1
+ using System.Reflection;
2
+ using System.Runtime.CompilerServices;
3
+ using System.Runtime.InteropServices;
4
+
5
+ // General Information about an assembly is controlled through the following
6
+ // set of attributes. Change these attribute values to modify the information
7
+ // associated with an assembly.
8
+ [assembly: AssemblyTitle("Service")]
9
+ [assembly: AssemblyDescription("")]
10
+ [assembly: AssemblyConfiguration("")]
11
+ [assembly: AssemblyCompany("")]
12
+ [assembly: AssemblyProduct("Service")]
13
+ [assembly: AssemblyCopyright("Copyright © 2006")]
14
+ [assembly: AssemblyTrademark("")]
15
+ [assembly: AssemblyCulture("")]
16
+
17
+ // Setting ComVisible to false makes the types in this assembly not visible
18
+ // to COM components. If you need to access a type in this assembly from
19
+ // COM, set the ComVisible attribute to true on that type.
20
+ [assembly: ComVisible(false)]
21
+
22
+ // The following GUID is for the ID of the typelib if this project is exposed to COM
23
+ [assembly: Guid("23fce5dd-8bf8-403c-b748-d24504e7c5c1")]
24
+
25
+ // Version information for an assembly consists of the following four values:
26
+ //
27
+ // Major Version
28
+ // Minor Version
29
+ // Build Number
30
+ // Revision
31
+ //
32
+ [assembly: AssemblyVersion("1.0.0.0")]
33
+ [assembly: AssemblyFileVersion("1.0.0.0")]
@@ -0,0 +1,17 @@
1
+ namespace DotNetServicesRuby
2
+ {
3
+ using System;
4
+ using System.Runtime.Serialization;
5
+ using System.ServiceModel;
6
+ using System.ServiceModel.Web;
7
+ using System.ServiceModel.Channels;
8
+
9
+ [ServiceContract(Name = "ResourceContract", Namespace = "http://samples.microsoft.com/ServiceModel/Relay/")]
10
+ public interface ResourceContract
11
+ {
12
+ [OperationContract(Action = "*", ReplyAction = "*")]
13
+ Message Process(Message message);
14
+ }
15
+
16
+ public interface ResourceChannel : ResourceContract, IClientChannel { }
17
+ }