CSLA.NET 6.0.0
CSLA .NET is a software development framework that helps you build a reusable, maintainable object-oriented business layer for your app.
GrpcPortal.cs
Go to the documentation of this file.
1//-----------------------------------------------------------------------
2// <copyright file="GrpcPortal.cs" company="Marimer LLC">
3// Copyright (c) Marimer LLC. All rights reserved.
4// Website: https://cslanet.com
5// </copyright>
6// <summary>Exposes server-side DataPortal functionality</summary>
7//-----------------------------------------------------------------------
8using System;
9using System.Collections.Generic;
10using System.IO;
11using System.Security.Principal;
12using System.Text;
13using System.Threading.Tasks;
14using Csla.Core;
17using Csla.Server;
19using Google.Protobuf;
20using Grpc.Core;
21
23{
28 public class GrpcPortal : Csla.Channels.Grpc.GrpcService.GrpcServiceBase
29 {
30 private IDataPortalServer dataPortalServer;
31 private ApplicationContext ApplicationContext { get; set; }
32
38 public GrpcPortal(IDataPortalServer dataPortal, ApplicationContext applicationContext)
39 {
40 dataPortalServer = dataPortal;
41 ApplicationContext = applicationContext;
42 }
43
50 public override async Task<ResponseMessage> Invoke(RequestMessage request, ServerCallContext context)
51 {
52 var operation = request.Operation;
53 if (operation.Contains("/"))
54 {
55 var temp = operation.Split('/');
56 return await RouteMessage(temp[0], temp[1], request);
57 }
58 else
59 {
60 return await InvokePortal(operation, request.Body).ConfigureAwait(false);
61 }
62 }
63
69 protected static Dictionary<string, string> RoutingTagUrls = new Dictionary<string, string>();
70
77 protected virtual async Task<ResponseMessage> RouteMessage(string operation, string routingTag, RequestMessage request)
78 {
79 if (RoutingTagUrls.TryGetValue(routingTag, out string route) && route != "localhost")
80 {
81 var options = new GrpcProxyOptions { DataPortalUrl = $"{route}?operation={operation}" };
82 var channel = ApplicationContext.CreateInstanceDI<global::Grpc.Net.Client.GrpcChannel>();
83 var proxy = new GrpcProxy(ApplicationContext, channel, options);
84 var clientRequest = new RequestMessage
85 {
86 Body = request.Body,
87 Operation = operation
88 };
89 var clientResponse = await proxy.RouteMessage(clientRequest);
90 return new ResponseMessage { Body = clientResponse.Body };
91 }
92 else
93 {
94 return await InvokePortal(operation, request.Body).ConfigureAwait(false);
95 }
96 }
97
98 private async Task<ResponseMessage> InvokePortal(string operation, ByteString requestData)
99 {
101 DataPortalErrorInfo errorData = null;
102 try
103 {
104 var request = SerializationFormatterFactory.GetFormatter(ApplicationContext).Deserialize(requestData.ToByteArray());
105 result = await CallPortal(operation, request);
106 }
107 catch (Exception ex)
108 {
110 }
112 portalResult.ErrorData = errorData;
113 portalResult.ObjectData = result.ObjectData;
114 var buffer = SerializationFormatterFactory.GetFormatter(ApplicationContext).Serialize(portalResult);
115 return new ResponseMessage { Body = ByteString.CopyFrom(buffer) };
116 }
117
118 private async Task<DataPortalResponse> CallPortal(string operation, object request)
119 {
120 DataPortalResponse result;
121 switch (operation)
122 {
123 case "create":
124 result = await Create((CriteriaRequest)request).ConfigureAwait(false);
125 break;
126
127 case "fetch":
128 result = await Fetch((CriteriaRequest)request).ConfigureAwait(false);
129 break;
130
131 case "update":
132 result = await Update((UpdateRequest)request).ConfigureAwait(false);
133 break;
134
135 case "delete":
136 result = await Delete((CriteriaRequest)request).ConfigureAwait(false);
137 break;
138
139 default:
140 throw new InvalidOperationException(operation);
141 }
142 return result;
143 }
144
149 public async Task<DataPortalResponse> Create(CriteriaRequest request)
150 {
152 try
153 {
154 request = ConvertRequest(request);
155
156 // unpack criteria data into object
157 object criteria = GetCriteria(ApplicationContext, request.CriteriaData);
159 {
160 criteria = ((Csla.DataPortalClient.PrimitiveCriteria)criteria).Value;
161 }
162
163 var objectType = Csla.Reflection.MethodCaller.GetType(AssemblyNameTranslator.GetAssemblyQualifiedName(request.TypeName), true);
164 var context = new DataPortalContext(
165 ApplicationContext, (IPrincipal)SerializationFormatterFactory.GetFormatter(ApplicationContext).Deserialize(request.Principal),
166 true,
167 request.ClientCulture,
168 request.ClientUICulture,
169 (ContextDictionary)SerializationFormatterFactory.GetFormatter(ApplicationContext).Deserialize(request.ClientContext));
170
171 var dpr = await dataPortalServer.Create(objectType, criteria, context, true);
172
173 if (dpr.Error != null)
174 result.ErrorData = ApplicationContext.CreateInstanceDI<DataPortalErrorInfo>(dpr.Error);
175 result.ObjectData = SerializationFormatterFactory.GetFormatter(ApplicationContext).Serialize(dpr.ReturnObject);
176 }
177 catch (Exception ex)
178 {
180 throw;
181 }
182 finally
183 {
184 result = ConvertResponse(result);
185 }
186 return result;
187 }
188
193 public async Task<DataPortalResponse> Fetch(CriteriaRequest request)
194 {
196 try
197 {
198 request = ConvertRequest(request);
199
200 // unpack criteria data into object
201 object criteria = GetCriteria(ApplicationContext, request.CriteriaData);
203 {
204 criteria = ((Csla.DataPortalClient.PrimitiveCriteria)criteria).Value;
205 }
206
207 var objectType = Csla.Reflection.MethodCaller.GetType(AssemblyNameTranslator.GetAssemblyQualifiedName(request.TypeName), true);
208 var context = new DataPortalContext(
209 ApplicationContext, (IPrincipal)SerializationFormatterFactory.GetFormatter(ApplicationContext).Deserialize(request.Principal),
210 true,
211 request.ClientCulture,
212 request.ClientUICulture,
213 (ContextDictionary)SerializationFormatterFactory.GetFormatter(ApplicationContext).Deserialize(request.ClientContext));
214
215 var dpr = await dataPortalServer.Fetch(objectType, criteria, context, true);
216
217 if (dpr.Error != null)
218 result.ErrorData = ApplicationContext.CreateInstanceDI<DataPortalErrorInfo>(dpr.Error);
219 result.ObjectData = SerializationFormatterFactory.GetFormatter(ApplicationContext).Serialize(dpr.ReturnObject);
220 }
221 catch (Exception ex)
222 {
224 throw;
225 }
226 finally
227 {
228 result = ConvertResponse(result);
229 }
230 return result;
231 }
232
237 public async Task<DataPortalResponse> Update(UpdateRequest request)
238 {
240 try
241 {
242 request = ConvertRequest(request);
243 // unpack object
244 object obj = GetCriteria(ApplicationContext, request.ObjectData);
245
246 var context = new DataPortalContext(
247 ApplicationContext, (IPrincipal)SerializationFormatterFactory.GetFormatter(ApplicationContext).Deserialize(request.Principal),
248 true,
249 request.ClientCulture,
250 request.ClientUICulture,
251 (ContextDictionary)SerializationFormatterFactory.GetFormatter(ApplicationContext).Deserialize(request.ClientContext));
252
253 var dpr = await dataPortalServer.Update(obj, context, true);
254
255 if (dpr.Error != null)
256 result.ErrorData = ApplicationContext.CreateInstanceDI<DataPortalErrorInfo>(dpr.Error);
257
258 result.ObjectData = SerializationFormatterFactory.GetFormatter(ApplicationContext).Serialize(dpr.ReturnObject);
259 }
260 catch (Exception ex)
261 {
263 throw;
264 }
265 finally
266 {
267 result = ConvertResponse(result);
268 }
269 return result;
270 }
271
276 public async Task<DataPortalResponse> Delete(CriteriaRequest request)
277 {
279 try
280 {
281 request = ConvertRequest(request);
282
283 // unpack criteria data into object
284 object criteria = GetCriteria(ApplicationContext, request.CriteriaData);
286 {
287 criteria = ((Csla.DataPortalClient.PrimitiveCriteria)criteria).Value;
288 }
289
290 var objectType = Csla.Reflection.MethodCaller.GetType(AssemblyNameTranslator.GetAssemblyQualifiedName(request.TypeName), true);
291 var context = new DataPortalContext(
292 ApplicationContext, (IPrincipal)SerializationFormatterFactory.GetFormatter(ApplicationContext).Deserialize(request.Principal),
293 true,
294 request.ClientCulture,
295 request.ClientUICulture,
296 (ContextDictionary)SerializationFormatterFactory.GetFormatter(ApplicationContext).Deserialize(request.ClientContext));
297
298 var dpr = await dataPortalServer.Delete(objectType, criteria, context, true);
299
300 if (dpr.Error != null)
301 result.ErrorData = ApplicationContext.CreateInstanceDI<DataPortalErrorInfo>(dpr.Error);
302 result.ObjectData = SerializationFormatterFactory.GetFormatter(ApplicationContext).Serialize(dpr.ReturnObject);
303 }
304 catch (Exception ex)
305 {
307 throw;
308 }
309 finally
310 {
311 result = ConvertResponse(result);
312 }
313 return result;
314 }
315
316 #region Criteria
317
318 private static object GetCriteria(ApplicationContext applicationContext, byte[] criteriaData)
319 {
320 object criteria = null;
321 if (criteriaData != null)
322 criteria = SerializationFormatterFactory.GetFormatter(applicationContext).Deserialize(criteriaData);
323 return criteria;
324 }
325
326 #endregion Criteria
327
328 #region Extention Method for Requests
329
335 protected virtual UpdateRequest ConvertRequest(UpdateRequest request)
336 {
337 return request;
338 }
339
346 {
347 return request;
348 }
349
356 {
357 return response;
358 }
359
360 #endregion Extention Method for Requests
361 }
362}
Csla.Server.DataPortalContext DataPortalContext
Provides consistent context information between the client and server DataPortal objects.
object CreateInstanceDI(Type objectType, params object[] parameters)
Creates an object using 'Activator.CreateInstance' using service provider (if one is available) to po...
Exposes server-side DataPortal functionality through gRPC.
Definition: GrpcPortal.cs:29
async Task< DataPortalResponse > Delete(CriteriaRequest request)
Delete a business object.
Definition: GrpcPortal.cs:276
static Dictionary< string, string > RoutingTagUrls
Gets a dictionary containing the URLs for each data portal route, where each key is the routing tag i...
Definition: GrpcPortal.cs:69
GrpcPortal(IDataPortalServer dataPortal, ApplicationContext applicationContext)
Creates an instance of the type
Definition: GrpcPortal.cs:38
async Task< DataPortalResponse > Create(CriteriaRequest request)
Create and initialize an existing business object.
Definition: GrpcPortal.cs:149
async Task< DataPortalResponse > Fetch(CriteriaRequest request)
Get an existing business object.
Definition: GrpcPortal.cs:193
virtual DataPortalResponse ConvertResponse(DataPortalResponse response)
Override to convert the response data after it comes back from the network.
Definition: GrpcPortal.cs:355
virtual CriteriaRequest ConvertRequest(CriteriaRequest request)
Override to convert the request data before it is transferred over the network.
Definition: GrpcPortal.cs:345
async Task< DataPortalResponse > Update(UpdateRequest request)
Update a business object.
Definition: GrpcPortal.cs:237
override async Task< ResponseMessage > Invoke(RequestMessage request, ServerCallContext context)
Handle inbound message.
Definition: GrpcPortal.cs:50
virtual UpdateRequest ConvertRequest(UpdateRequest request)
Override to convert the request data before it is transferred over the network.
Definition: GrpcPortal.cs:335
virtual async Task< ResponseMessage > RouteMessage(string operation, string routingTag, RequestMessage request)
Entry point for routing tag based data portal operations.
Definition: GrpcPortal.cs:77
Implements a data portal proxy to relay data portal calls to a remote application server by using gRP...
Definition: GrpcProxy.cs:20
Dictionary type that is serializable with the SerializationFormatterFactory.GetFormatter().
Class used as a wrapper for criteria based requests that use primitives
Message sent to the WCF data portal.
string ClientCulture
Serialized client culture.
byte[] CriteriaData
Serialized data for the criteria object.
string TypeName
Assembly qualified name of the business object type to create.
byte[] ClientContext
Serialized data for the client context object.
byte[] Principal
Serialized data for the principal object.
string ClientUICulture
Serialized client UI culture.
Message containing details about any server-side exception.
Response message for returning the results of a data portal call.
DataPortalErrorInfo ErrorData
Server-side exception data if an exception occurred on the server.
Request message for updating a business object.
byte[] ClientContext
Serialized data for the client context object.
string ClientCulture
Serialized client culture.
string ClientUICulture
Serialized client UI culture.
byte[] Principal
Serialized data for the principal object.
Interface implemented by server-side data portal components.
Task< DataPortalResult > Update(object obj, DataPortalContext context, bool isSync)
Update a business object.
Task< DataPortalResult > Create(Type objectType, object criteria, DataPortalContext context, bool isSync)
Create a new business object.
Task< DataPortalResult > Fetch(Type objectType, object criteria, DataPortalContext context, bool isSync)
Get an existing business object.
Task< DataPortalResult > Delete(Type objectType, object criteria, DataPortalContext context, bool isSync)
Delete a business object.