Plugin bypassed when Entity queried from console application - dynamics-crm-2011

My plugin encrypts/decrypts a field. Works on the field within a CRM form.
From my console application, a retrieve bypasses my plugin, e.g., it retrieves the encrypted value directly from the database without running the plugin. When debugging, breakpoints in the plugin are hit when the field is accessed from a form , but they are not hit when accessed from my console program.
I'm surprised that my plugin isn't invoked from a program. It bypasses my business rules.
Here is how I'm accessing the entity and the field from a program:
private static OrganizationServiceProxy service = null;
private static OrganizationServiceContext orgSvcContext = null;
public static void RetrieveSSNs()
{
var query = orgSvcContext.CreateQuery("bpa_consumer");
foreach (Entity consumer in query)
{
if (consumer.Attributes.Contains("bpa_ssn"))
{
string ssn = consumer["bpa_ssn"].ToString();
Console.WriteLine(string.Format("Consumer \"{0}\" has SSN {1}", consumer.Attributes["bpa_name"], ssn));
}
else
{
Console.WriteLine(string.Format("Consumer \"{0}\" doesn't have a SSN", consumer.Attributes["bpa_name"]));
}
}
}

I'm guessing you have the plugin registered on the Retrieve method? If so, add another identical registration on the RetrieveMultiple. This should get your plugin to execute on your foreach. I should warn you that this is an extremely dangerous thing to do from a performance standpoint though...

If you are concerned about performance my recommendation is to put the encrypted data into a separate entity with a lookup back. Using this method CRM only has to execute the Retrieve/RetrieveMultiple plug-in when a user needs to access the encrypted data, not every time a user accesses the primary record. This will also make it easier to secure the encrypted data.

Turns out the you must register your plugin for the event RetrieveMultiple when you query for a collection of Entities.

Related

ServiceStack: business logic that depends on the database itself

I'm exploring ServiceStack and I'm not sure what is the best way to implement some business logic.
Using the "Bookings CRUD" example I would like to enforce the following rule:
a given Booking can only be saved (either created or updated) if the hotel has enough free rooms for the particular dates of that booking
Please note that I'm not asking how to calculate "free rooms".
What I'm asking is, from the architectural point of view, how should this be done.
For example, one way would be:
create a request DTO to query the number of configured rooms (lets call it "QueryRooms")
use the existing "QueryBookings" to query current bookings present in database
create a " : Service" class to customize the Booking Service, in order to intercept the "CreateBooking" and "UpdateBooking" requests
inside the custom methods for "CreateBooking" and "UpdateBooking", somehow get the results of "QueryRooms" and "QueryBookings", check if there are enough free rooms for the current request, and proceed only if so
This doesn't look very clean, because the service "CreateBooking" and "UpdateBooking" would depend of "QueryRooms" and "QueryBookings".
What would be an elegant and effcient solution, using ServiceStatck?
You can override AutoQuery CRUD operations with your own Service implementation using the AutoQuery DTO.
Where you can use the Service Gateway to call existing Services which you can use to perform any additional validation & modify the request DTO before executing the AutoQuery operation to implement the API, e.g:
public class MyCrudServices : Service
{
public IAutoQueryDb AutoQuery { get; set; }
public object Post(CreateBooking request)
{
var response = Gateway.Send(new QueryRooms
{
From = request.BookingStartDate,
To = request.BookingEndDate,
});
if (response.Results.Count == 0)
throw new Exception("No rooms available during those dates");
request.RoomNumber = response.Results[0].Id;
return AutoQuery.Create(request, base.Request);
}
}
Note: calling in-process Services with the Service Gateway is efficient as it calls the C# method implementation directly, i.e. without incurring any HTTP overhead.

Automatic binding to some service properties in Catel with Fody

Assuming there is some service:
public interface IDeviceManagerService
{
ISomeDeviceApi Api { get; }
}
It's purpose is to monitor external environment (USB, network, etc.), instantiate device API when the device detected and make property null when the device is no longer available.
Supposing there is a view model with this service injected, I would like to have change notifications for IDeviceManagerService.Api to make things like below possible (for example, having the button which is only active when the device API is available).
private Boolean OnSomeCommandCanExecute()
{
return _deviceManagerService.Api != null;
}
I wonder if there is a clean way to make this work without manual change notifications handling (with Catel.Fody or PropertyChanged.Fody). So far I have managed to get working result by making service implementation derived from ModelBase, registering it's injected instance as a [Model] inside the view model and exposing it's Api property using [ViewModelToModel] attribute, but this is very dirty way.
Is there some common approach or It would be better to go with implementing INotifyPropertyChanged and use notifications wrapper instead?
In most approaches, services don't implement INotifyPropertyChanged (they are not models), so my recommendation is to add manual events:
public interface IDeviceManagerService
{
ISomeDeviceApi Api { get; }
event EventHandler<DeviceApiEventArgs> ApiChanged;
}
This way you can deal with the stuff you are interested in (subscribe in InitializeAsync, unsubscribe in CloseAsync).

Why is data access tightly coupled to the Service base in ServiceStack

I'm curious why the decision was made to couple the Service base class in ServiceStack to data access (via the Db property)? With web services it is very popular to use a Data Repository pattern to fetch the raw data from the database. These data repositories can be used by many services without having to call a service class.
For example, let's say I am supporting a large retail chain that operates across the nation. There are a number of settings that will differ across all stores like tax rates. Each call to one of the web services will need these settings for domain logic. In a repository pattern I would simply create a data access class whose sole responsibility is to return these settings. However in ServiceStack I am exposing these settings as a Service (which it needs to be as well). In my service call the first thing I end up doing is newing up the Setting service and using it inside my other service. Is this the intention? Since the services return an object I have to cast the result to the typed service result.
ServiceStack convenience ADO.NET IDbConnection Db property allows you to quickly create Database driven services (i.e. the most popular kind) without the overhead and boilerplate of creating a repository if preferred. As ServiceStack Services are already testable and the DTO pattern provides a clean endpoint agnostic Web Service interface, there's often not a lot of value in wrapping and proxying "one-off" data-access into a separate repository.
But at the same time there's nothing forcing you to use the base.Db property, (which has no effect if unused). The Unit Testing Example on the wiki shows an example of using either base.Db or Repository pattern:
public class SimpleService : Service
{
public IRockstarRepository RockstarRepository { get; set; }
public List<Rockstar> Get(FindRockstars request)
{
return request.Aged.HasValue
? Db.Select<Rockstar>(q => q.Age == request.Aged.Value)
: Db.Select<Rockstar>();
}
public RockstarStatus Get(GetStatus request)
{
var rockstar = RockstarRepository.GetByLastName(request.LastName);
if (rockstar == null)
throw HttpError.NotFound("'{0}' is no Rockstar".Fmt(request.LastName));
var status = new RockstarStatus
{
Alive = RockstarRepository.IsAlive(request.LastName)
}.PopulateWith(rockstar); //Populates with matching fields
return status;
}
}
Note: Returning an object or a strong-typed DTO response like RockstarStatus have the same effect in ServiceStack, so if preferred you can return a strong typed response and avoid any casting.

ServiceStack OrmLite Is it a error to use UserAuthRepository.CreateUserAuth inside a transaction

I have a complex workflow where I want to create rows in several tables in one transaction.
One of the operations is to create a new UserAuth (from ServiceStack Authentication feature).
I assume that all the database operations in a transaction should operate on the same connection, and if that is true, then I think it may be a problem to call UserAuthRepository.CreateUserAuth inside a transaction because it looks as if it uses its own connection.
So my question is whether if the creation of a UserAuth will be part of the transaction or not when I have code like shown below. And if not, then how to go about creating new users as part of an transaction?
using (var db = Db.OpenDbConnection()) {
using (var trans = db.OpenTransaction()) {
... do some databae operations via. db ...
var userAuth = UserAuthRepository.CreateUserAuth(
new UserAuth{UserName = "blabla"},
"password"
);
... do some more databae operations via. db ...
trans.Commit();
}
}
Internally whenever ServiceStack requires accessing a database, e.g in the OrmLiteUserAuthRepository.CreateUserAuth it asks for and uses a new connection and immediately disposes of it once it's done.
There is currently no way to make it apart of a custom transaction.

How to use ASP.NET Session State in an HttpHandler?

I have an HttpHandler that is run on a client page (cross domain, not on our IIS server, etc) and when they click on our embedded link it fires off the Handler on our server. So far everything is working normally.
I am now trying to use the System.Web.HttpContext.Session object but it is null. I am thinking it is null because we don't have a session until our HttpHandler is invoked? And multiple calls to the handler will create a new session per call? If this is the case did MS just disable the Session object when calling into a HttpHandler? Can anyone confirm this?
If this is the case, what do you do to maintain state between calls? Some sort of SQL based data object? A file?
TIA
Have your HttpHandler implement the IRequiresSessionState interface. It will enable session state use.
IRequiresSessionState can be found in the System.Web.SessionState namespace.
I think you have to implement the empty interface IReadOnlySessionState, so the context will be loaded.
edit to add:
According to Michael Morton's answer, you can also implement IRequiresSessionState, which will give you write access also to the Session object
using System;
using System.Web;
using System.Web.SessionState;
public class DownloadHandler : IHttpHandler, IReadOnlySessionState
{
public bool IsReusable { get { return true; } }
public void ProcessRequest(HttpContext context)
{
context.Response.Write(context.Session["kmx"]);
}
}
try using the current context...
System.Web.HttpContext.Current.Session

Resources