9using System.Globalization;
11using System.Threading.Tasks;
33 DataPortalProxy = proxy;
40 private DataPortalClient.IDataPortalProxy DataPortalProxy {
get;
set; }
42 private class DataPortalAsyncRequest
44 private ApplicationContext ApplicationContext {
get;
set; }
46 public object Argument {
get;
set; }
47 public System.Security.
Principal.IPrincipal Principal {
get;
set; }
49 public object UserState {
get;
set; }
51 public CultureInfo CurrentCulture;
52 public CultureInfo CurrentUICulture;
54 public DataPortalAsyncRequest(ApplicationContext applicationContext,
object argument,
object userState)
56 ApplicationContext = applicationContext;
57 this.Argument = argument;
58 this.Principal = ApplicationContext.User;
59 this.ClientContext = ApplicationContext.ClientContext;
60 this.UserState = userState;
61 this.CurrentCulture = System.Globalization.CultureInfo.CurrentCulture;
62 this.CurrentUICulture = System.Globalization.CultureInfo.CurrentUICulture;
66 private class DataPortalAsyncResult
68 public T Result {
get;
set; }
69 public object UserState {
get;
set; }
70 public Exception
Error {
get;
set; }
72 public DataPortalAsyncResult(T result, Exception error,
object userState)
75 this.UserState = userState;
80 private Reflection.ServiceProviderMethodCaller serviceProviderMethodCaller;
81 private Reflection.ServiceProviderMethodCaller ServiceProviderMethodCaller
85 if (serviceProviderMethodCaller ==
null)
86 serviceProviderMethodCaller = (Reflection.ServiceProviderMethodCaller)ApplicationContext.
CreateInstanceDI(typeof(Reflection.ServiceProviderMethodCaller));
87 return serviceProviderMethodCaller;
91 private async Task<object> DoCreateAsync(Type objectType,
object criteria,
bool isSync)
93 Server.DataPortalResult result =
null;
94 Server.DataPortalContext dpContext =
null;
102 Reflection.ServiceProviderMethodInfo method;
103 if (criteria is Server.EmptyCriteria)
104 method = ServiceProviderMethodCaller.FindDataPortalMethod<CreateAttribute>(objectType,
null,
false);
106 method = ServiceProviderMethodCaller.FindDataPortalMethod<CreateAttribute>(objectType, Server.DataPortal.GetCriteriaArray(criteria),
false);
107 var proxy = GetDataPortalProxy(method);
114 result = await proxy.Create(objectType, criteria, dpContext, isSync);
116 catch (AggregateException ex)
118 if (ex.InnerExceptions.Count > 0)
120 if (ex.InnerExceptions[0] is Server.DataPortalException dpe)
121 HandleCreateDataPortalException(dpe, isSync, proxy);
123 throw new DataPortalException(
127 catch (Server.DataPortalException ex)
129 HandleCreateDataPortalException(ex, isSync, proxy);
136 return result.ReturnObject;
141 HandleDataPortalException(
"Create", ex, isSync, proxy);
151 public T
Create(params
object[] criteria)
153 return (T)
Create(typeof(T), Server.DataPortal.GetCriteriaFromArray(criteria));
163 private object Create(Type objectType,
object criteria)
167 return DoCreateAsync(objectType, criteria,
true).Result;
169 catch (AggregateException ex)
171 if (ex.InnerExceptions.Count > 0)
172 throw ex.InnerExceptions[0];
186 return (T)await DoCreateAsync(typeof(T), Server.DataPortal.GetCriteriaFromArray(criteria),
false);
189 private async Task<object> DoFetchAsync(Type objectType,
object criteria,
bool isSync)
191 Server.DataPortalResult result =
null;
192 Server.DataPortalContext dpContext =
null;
201 var method = ServiceProviderMethodCaller.FindDataPortalMethod<
FetchAttribute>(objectType, Server.DataPortal.GetCriteriaArray(criteria),
false);
202 var proxy = GetDataPortalProxy(method);
209 result = await proxy.Fetch(objectType, criteria, dpContext, isSync);
211 catch (AggregateException ex)
213 if (ex.InnerExceptions.Count > 0)
215 var dpe = ex.InnerExceptions[0] as Server.DataPortalException;
217 HandleFetchDataPortalException(dpe, isSync, proxy);
219 throw new DataPortalException(
223 catch (Server.DataPortalException ex)
225 HandleFetchDataPortalException(ex, isSync, proxy);
232 return result.ReturnObject;
237 HandleDataPortalException(
"Fetch", ex, isSync, proxy);
247 public T
Fetch(params
object[] criteria)
249 return (T)
Fetch(typeof(T), Server.DataPortal.GetCriteriaFromArray(criteria));
258 private object Fetch(Type objectType,
object criteria)
262 return DoFetchAsync(objectType, criteria,
true).Result;
264 catch (AggregateException ex)
266 if (ex.InnerExceptions.Count > 0)
267 throw ex.InnerExceptions[0];
281 return (T)await DoFetchAsync(typeof(T), Server.DataPortal.GetCriteriaFromArray(criteria),
false);
284 internal async Task<T> DoUpdateAsync(T obj,
bool isSync)
286 Server.DataPortalResult result =
null;
287 Server.DataPortalContext dpContext =
null;
288 Type objectType = obj.GetType();
291 DataPortalClient.IDataPortalProxy proxy =
null;
293 if (factoryInfo !=
null)
296 var factoryLoader =
ApplicationContext.CurrentServiceProvider.GetService(typeof(Server.IObjectFactoryLoader)) as Server.IObjectFactoryLoader;
297 var factoryType = factoryLoader?.GetFactoryType(factoryInfo.FactoryTypeName);
299 if (obj is Core.ICommandObject)
305 if (factoryType !=
null)
306 method = Server.DataPortalMethodCache.GetMethodInfo(factoryType, factoryInfo.ExecuteMethodName,
new object[] { obj });
310 if (obj is Core.BusinessBase bbase)
318 if (factoryType !=
null)
319 method = Server.DataPortalMethodCache.GetMethodInfo(factoryType, factoryInfo.DeleteMethodName,
320 new object[] { obj });
323 else if (bbase.IsNew)
329 if (factoryType !=
null)
330 method = Server.DataPortalMethodCache.GetMethodInfo(factoryType, factoryInfo.UpdateMethodName,
331 new object[] { obj });
339 if (factoryType !=
null)
340 method = Server.DataPortalMethodCache.GetMethodInfo(factoryType, factoryInfo.UpdateMethodName,
341 new object[] { obj });
351 if (factoryType !=
null)
352 method = Server.DataPortalMethodCache.GetMethodInfo(factoryType, factoryInfo.UpdateMethodName,
353 new object[] { obj });
358 proxy = GetDataPortalProxy(method.RunLocal);
362 Reflection.ServiceProviderMethodInfo method;
363 var criteria = Server.DataPortal.GetCriteriaArray(Server.EmptyCriteria.Instance);
364 if (obj is Core.ICommandObject)
370 method = ServiceProviderMethodCaller.FindDataPortalMethod<ExecuteAttribute>(objectType, criteria,
false);
374 if (obj is Core.BusinessBase bbase)
382 method = ServiceProviderMethodCaller.FindDataPortalMethod<DeleteSelfAttribute>(objectType, criteria,
false);
384 else if (bbase.IsNew)
390 method = ServiceProviderMethodCaller.FindDataPortalMethod<InsertAttribute>(objectType, criteria,
false);
398 method = ServiceProviderMethodCaller.FindDataPortalMethod<UpdateAttribute>(objectType, criteria,
false);
403 method = ServiceProviderMethodCaller.FindDataPortalMethod<UpdateAttribute>(objectType, criteria,
false);
406 proxy = GetDataPortalProxy(method);
410 new Server.DataPortalContext(ApplicationContext, GetPrincipal(), proxy.IsServerRemote);
418 if (obj is ICloneable cloneable)
419 obj = (T)cloneable.Clone();
421 result = await proxy.Update(obj, dpContext, isSync);
423 catch (AggregateException ex)
425 if (ex.InnerExceptions.Count > 0)
427 if (ex.InnerExceptions[0] is Server.DataPortalException dpe)
428 HandleUpdateDataPortalException(dpe, isSync, proxy);
430 throw new DataPortalException(
434 catch (Server.DataPortalException ex)
436 HandleUpdateDataPortalException(ex, isSync, proxy);
443 return (T)result.ReturnObject;
448 HandleDataPortalException(
"Update", ex, isSync, proxy);
453 var result = ex.Result;
454 var original = ex.InnerException;
455 if (original.InnerException !=
null)
456 original = original.InnerException;
457 throw new DataPortalException(
459 ex.InnerException, result.ReturnObject);
471 return DoUpdateAsync(obj,
true).Result;
473 catch (AggregateException ex)
475 if (ex.InnerExceptions.Count > 0)
476 throw ex.InnerExceptions[0];
489 return await DoUpdateAsync(obj,
false);
492 internal async Task DoDeleteAsync(Type objectType,
object criteria,
bool isSync)
494 Server.DataPortalResult result =
null;
495 Server.DataPortalContext dpContext =
null;
503 var method = ServiceProviderMethodCaller.FindDataPortalMethod<
DeleteAttribute>(objectType, Server.DataPortal.GetCriteriaArray(criteria),
false);
504 var proxy = GetDataPortalProxy(method);
506 dpContext =
new Server.DataPortalContext(
ApplicationContext, GetPrincipal(), proxy.IsServerRemote);
510 result = await proxy.Delete(objectType, criteria, dpContext, isSync);
512 catch (AggregateException ex)
514 if (ex.InnerExceptions.Count > 0)
516 var dpe = ex.InnerExceptions[0] as Server.DataPortalException;
518 HandleDeleteDataPortalException(dpe, isSync, proxy);
520 throw new DataPortalException(
524 catch (Server.DataPortalException ex)
526 HandleDeleteDataPortalException(ex, isSync, proxy);
537 HandleDataPortalException(
"Delete", ex, isSync, proxy);
545 public void Delete(params
object[] criteria)
547 Delete(typeof(T), Server.DataPortal.GetCriteriaFromArray(criteria));
556 private void Delete(Type objectType,
object criteria)
560 var task = DoDeleteAsync(objectType, criteria,
true);
561 if (!task.IsCompleted)
562 task.RunSynchronously();
563 if (task.Exception !=
null)
564 throw task.Exception;
566 catch (AggregateException ex)
568 if (ex.InnerExceptions.Count > 0)
569 throw ex.InnerExceptions[0];
582 await DoDeleteAsync(typeof(T), Server.DataPortal.GetCriteriaFromArray(criteria),
false);
602 return await DoUpdateAsync(command,
false);
605 private DataPortalClient.IDataPortalProxy GetDataPortalProxy(Reflection.ServiceProviderMethodInfo method)
608 return GetDataPortalProxy(method.MethodInfo.RunLocal());
610 return GetDataPortalProxy(
false);
613 private DataPortalClient.IDataPortalProxy GetDataPortalProxy(
bool forceLocal)
615 if (forceLocal || ApplicationContext.
IsOffline)
618 return DataPortalProxy;
621 private System.Security.Principal.IPrincipal GetPrincipal()
631 return ApplicationContext.
User;
642 return (T)(portal.Create(typeof(T)));
655 return (T)(portal.Create(typeof(T), parameters));
665 return await portal.CreateAsync<T>();
678 return await portal.CreateAsync<T>(parameters);
688 return (T)(portal.Fetch(typeof(T)));
701 return (T)(portal.Fetch(typeof(T), parameters));
711 return await portal.FetchAsync<T>();
724 return await portal.FetchAsync<T>(parameters);
737 portal.Update(child);
753 portal.Update(child, parameters);
769 portal.Update(child, parameters);
782 await portal.UpdateAsync(child).ConfigureAwait(
false);
798 await portal.UpdateAsync(child, parameters).ConfigureAwait(
false);
818 internal static class Extensions
820 internal static bool RunLocal(
this System.Reflection.MethodInfo t)
822 return t.CustomAttributes.Count(a => a.AttributeType.Equals(typeof(RunLocalAttribute))) > 0;
Provides consistent context information between the client and server DataPortal objects.
static bool AutoCloneOnUpdate
Gets a value indicating whether objects should be automatically cloned by the data portal Update() me...
bool IsOffline
Gets or sets a value indicating whether the app should be considered "offline".
object CreateInstanceDI(Type objectType, params object[] parameters)
Creates an object using 'Activator.CreateInstance' using service provider (if one is available) to po...
static string AuthenticationType
Gets the authentication type being used by the CSLA .NET framework.
IPrincipal User
Get or set the current IPrincipal object representing the user's identity.
ClaimsPrincipal Principal
Get or set the current ClaimsPrincipal object representing the user's identity.
Implements a data portal proxy to relay data portal calls to an application server hosted locally in ...
Dictionary type that is serializable with the SerializationFormatterFactory.GetFormatter().
Client side data portal used for making asynchronous data portal calls in .NET.
T CreateChild()
Creates and initializes a new child business object.
async Task UpdateChildAsync(T child)
Inserts, updates or deletes an existing child business object.
void Delete(params object[] criteria)
Called by a factory method in a business class or by the UI to delete an object.
T Execute(T command)
Called by a factory method in a business class or by the UI to execute a command object.
async Task< T > CreateChildAsync()
Creates and initializes a new child business object.
async Task< T > CreateAsync(params object[] criteria)
Called by a factory method in a business class or by the UI to create a new object,...
T CreateChild(params object[] parameters)
Creates and initializes a new child business object.
void UpdateChild(T child)
Inserts, updates or deletes an existing child business object.
async Task< T > FetchChildAsync()
Fetches an existing child business object.
async Task DeleteAsync(params object[] criteria)
Called by a factory method in a business class or by the UI to delete an object.
T Update(T obj)
Called by a factory method in a business class or by the UI to update an object.
async Task UpdateChildAsync(T child, params object[] parameters)
Inserts, updates or deletes an existing child business object.
T Create(params object[] criteria)
Called by a factory method in a business class to create a new object, which is loaded with default v...
DataPortal(ApplicationContext applicationContext, DataPortalClient.IDataPortalProxy proxy)
Creates an instance of the type
async Task< T > ExecuteAsync(T command)
Called by a factory method in a business class or by the UI to execute a command object.
async Task< T > FetchChildAsync(params object[] parameters)
Fetches an existing child business object.
T Fetch(params object[] criteria)
Called by a factory method in a business class to Fetch a new object, which is loaded with default va...
async Task< T > UpdateAsync(T obj)
Called by a factory method in a business class or by the UI to update an object.
T FetchChild(params object[] parameters)
Fetches an existing child business object.
void UpdateChild(object child, params object[] parameters)
Inserts, updates or deletes an existing child business object.
async Task< T > FetchAsync(params object[] criteria)
Called by a factory method in a business class or by the UI to Fetch a new object,...
T FetchChild()
Fetches an existing child business object.
async Task< T > CreateChildAsync(params object[] parameters)
Creates and initializes a new child business object.
void UpdateChild(T child, params object[] parameters)
Inserts, updates or deletes an existing child business object.
Specifies a method used by the server-side data portal to delete domain object data during an update ...
Specifies a method used by the server-side data portal to load existing data into the domain object.
A strongly-typed resource class, for looking up localized strings, etc.
static string Failed
Looks up a localized string similar to failed.
static string UserNotAuthorizedException
Looks up a localized string similar to User not authorized to {0} object type {1}.
Tracks the business rules for a business object.
static bool HasPermission(ApplicationContext applicationContext, AuthorizationActions action, Type objectType)
Checks per-type authorization rules.
Provides consistent context information between the client and server DataPortal objects.
Specifies that the data portal should invoke a factory object rather than the business object.
Interface implemented by client-side data portal proxy objects.
Interface defining the members of the child data portal type.
Task UpdateChildAsync(object obj, params object[] parameters)
Called by a factory method in a business class or by the UI to update an object.
Task< object > FetchChildAsync(params object[] criteria)
Starts an asynchronous data portal operation to create a business object.
Task< object > CreateChildAsync(params object[] criteria)
Starts an asynchronous data portal operation to create a business object.
object CreateChild(params object[] criteria)
Called by a factory method in a business class to create a new object, which is loaded with default v...
void UpdateChild(object obj, params object[] parameters)
Called by the business object's Save() method to insert, update or delete an object in the database.
object FetchChild(params object[] criteria)
Called by a factory method in a business class to retrieve an object, which is loaded with values fro...
Interface defining the members of the data portal type.
object Update(object obj)
Insert, update or delete an object in the database.
Task< object > CreateAsync(params object[] criteria)
Starts an asynchronous data portal operation to create a business object.
object Fetch(params object[] criteria)
Called by a factory method in a business class to retrieve an object, which is loaded with values fro...
Task< object > UpdateAsync(object obj)
Called by a factory method in a business class or by the UI to update an object.
object Execute(object obj)
Called to execute a Command object on the server.
Task< object > ExecuteAsync(object command)
Called by a factory method in a business class or by the UI to execute a command object.
object Create(params object[] criteria)
Called by a factory method in a business class to create a new object, which is loaded with default v...
Task< object > FetchAsync(params object[] criteria)
Starts an asynchronous data portal operation to create a business object.
@ Error
Represents a serious business rule violation that should cause an object to be considered invalid.