Unable to use methods from Domain Service class in WCF Ria? - c#

I am trying to build an silverlight application which takes user first name, last name, pass, email address in text boxes and then add these to the database.
For this i am using WCF Ria Services.
Steps i have followed are :
Added ADO.NET Entity Data Model and then Domain Service class in my project (in web part).
Now i have got some predefined methods in my DomainService Class like Insert, Update methods. I know how to show data in DataGrid but its not what i want.
What i want is to customize all this for :
When user clicks the submit button then there should be method inside this like AddInfo(all parameters) which can add all the data to my sql server database {at present LocalHost}.
In simple words accessing your database through custom methods to add data in sql server using WCF Ria Services
I know it was very simple while working in .net forms and all. But how about Silverlight & WCF ria ?
Please Suggest.

In simple words accessing your database through custom methods to add
data in sql server using WCF Ria Services
What you should do is write a custom method in server-side.
On server-side, you have a DomainService class that should inherit from LinqToEntitiesDomainService<TContext>.
Simply add a method in this class with the Invoke attribute, for example:
[Invoke]
public void AddNewUser(string name, string firstName, int age)
{
// Put logic here to add the user to the DB
}
The logic to add a user to the database is really simple, just create a new Entity, add it to the context and call context.SubmitChanges();
When you compile the client RIA Services project, the auto-generated proxy class that correspond to your DomainService will contain your new method, and you'll be able to call it using:
yourDomainContext ctx = new yourDomainContext();
ctx.AddNewUser("dsd", "ds", 42).Completed += (sender, e) =>
{
// Called asynchronously when the job is done
};

If you already have the Insert method on your Domain Service, you should be able to call from the client:
//add your new data to the context
MyDomainServiceContext.Entity.Add(myEntity); //(where "Entity" is your entity Type)
//send all the changes to the server
MyDomainServiceContext.SubmitChanges();

Related

IdentityServer 4, Create Panel to CRUD Clients

Currently I Have configured Identityserver4 as separated project + My WebAPI and store in DB Credentials in IdentityServer.
Now i have problem how to make CRUD(In my frontend API) to IdentityServer(I want from my API add Clients to IdentityServer)
How to make property?
From IdentityServer4.EntityFramework and IdentityServer4.EntityFramework.Storage, you have access to IConfigurationDbContext (once you've added the required services in ConfigureServices using e.g. AddConfigurationStore). Because this is registered as part of the Dependency Injection system, you can take a dependency on it in one of your controllers. e.g.:
public class ClientsController : ControllerBase
{
private readonly IConfigurationDbContext _configurationDbContext;
public ClientsController(IConfigurationDbContext configurationDbContext)
{
_configurationDbContext = configurationDbContext;
}
// ...
}
IConfigurationDbContext is an abstraction of a standard DbContext, with the following DbSet<T> properties:
Clients
IdentityResources
ApiResources
It also includes both SaveChanges and SaveChangesAsync - Everything one might expect from a DbContext. Because of all of this, you can CRUD each of these entities just like any other Entity Framework Core driven database.
One final thing to note is that there are both Models (in IdentityServer4.Storage) and Entities (in IdentityServer4.EntityFramework.Storage). There are also a few extension methods for mapping between these (e.g. ClientMappers.ToEntity).
Given all of this, you can create a Model inside of your controller (or perhaps somewhere much better encapsulated than directly there). Here's a basic example for creating a new Client:
var clientModel = new Client
{
ClientId = "",
ClientName = "",
// ...
};
_configurationDbContext.Clients.Add(clientModel.ToEntity());
await _configurationDbContext.SaveChangesAsync();
The Client class here comes from IdentityServer4.Models and is then converted to an Entity using a ToEntity extension method I hinted at above. Working with a Model and converting to an Entity is simpler than trying to manipulate an Entity directly - If you're interested, you can see the mapping that takes place here.
This works in the same way for ApiResources, IdentityResources, etc. Use the source code links I've provided if you want to find out more about those specifically, but the information I've provided here should have you covered.
In order to use IdentityServer4 and IdentityServer4.EntityFramework in your API project, you can just add the two references to your API project. After that, you can configure the DI in the same way (using AddIdentityServer in ConfigureServices), but you don't need to add the middleware (using UseIdentityServer in Configure). You can even just use AddIdentityServer().AddConfigurationStore(...) to set up the relevant services, as you don't need a signing key, etc.
One way you can do this is by bootstrapping the ID4 Quickstart (tutorial located here):
http://docs.identityserver.io/en/release/quickstarts/3_interactive_login.html
Other option is to use their quickstart seeds located here to speed this up:
https://github.com/IdentityServer/IdentityServer4.Samples
Now if you want to implement restfull login there are constraints around it (i wanted to find out as well) check out this question:
IdentityServer 4 Restfull Login/Logout

How can I dynamically set connection string in MVC 5 based on incoming request?

I have an MVC 5 application that is currently single tenant only, but that is becoming unmanageable as our client-base grows.
I would like to turn this application into a multi-tenant app, accessing a distinct database for each client.
The client's are easily distinguishable by their domain, which I can access through Request.Url.Host or other methods, but once I have this property, I am having trouble setting it in the Business logic project within the context of that request only.
The Business logic project is referenced by the main Web project, but that project is blink to the Request object, so I do not know how to get that session information dynamically each time the baseDataAccess (which contains the connection strings) object is instantiated.
I've spent many many hours on this, and have tried using Ninject to resolve the dependency with no success. I just can't seem to figure out how to get the dynamic Request object or any of its properties to assign transiently to the baseDataAccess object.
The last thing I tried was using and IActionFilter using the OnActionExecuting method, but I am still unable to figure out how to set the value of the URL for each request dynamically in a project that has no context for the current request.
This is the class I want to set dynamically. the _connectionString is the dynamic property. I have methods to build the connection string based on the url, so if I can set the _domain property dynamically and transiently I'll be able to get the connection string.
public class baseDataAccess : IDataAccess
{
private static IClientConnection _clientConnection;
private static string _connectionString;
public static string _domain;
...
This is the last attempt I made, adding the OnActionExecuting method to each controller. How can I set these properties dynamically and transiently?
public void OnActionExecuting(ActionExecutedContext filterContext)
{
IClientConnection client = new ClientConnectionFactory(Request.Url.Host);
IDataAccess dataAccess = new baseDataAccess(client);
}
I'm have the same need for my application. I have to set the connection String with the user information depending on the user login. I added a reference on System.Web to get the Session object in my business layer.
The main idea is, to store the current user in the Session and let the business logic access this Session with HttpContext.Current.Session now my database classes can read the connection string dynamically on every single access to the database.
And as the user session is available in any library that has the System.Web reference, it can be used application wide. So there is no problem setting the connection string on the Session_Start event depending on the request from the user.

How to have a core class call a Client Class?

I am trying to build a core application that uses plugins so that the core never changes and each time we get a new client we write a module for them. We implement a interface called IClientPlugin with the new customer class.
This is using Compact Framework 3.5 and windows mobile 6.5.3.
So here is what I need to acheive:
this is a warehouse management system. The first task is to receive in the product from a truck scanning barcodes off packages with the handheld device.
The core module for this is started when the person clicks the receiving menu item.
the core method is - callClientMethod()
I know the client name and it is stored in a global variable at login and the class will be {clientname}.cs
and contain a method called processReceiving().
I know how to instantiate this object.
The question is: is there a way I can dynamically create a instance of the client class without hardcoding case statements?
For example suppose I have 2 clients Acme and Widgets. They each get a client class, namely Acme.cs and Widgets.cs
If I login as Acme or Widgets I want the code to dynamically create a instance of the Client class that I logged in as so that the core code does not have to change as I add more clients as long as I add a module for them.
psuedo example:
var myClient = New (Clientname)();
Is this possible or is there a better design approach or is the switch/case statement a neccessary evil?
You can use reflection to create objects dynamically.
There are many ways to load a type or assembly. Lets start with a simple one:
Type clientType = Type.GetType("AssemblyName, TypeName");
IClientPlugin clientPlugin =
(IClientPlugin)Activator.CreateInstance(clientType);
If your client is named myClient1 and you have the convention, that your assemblies are named for example like Clients.ClientName.dll then you can write a function:
IClientPlugin CreatePluginInstance(string clientName) {
string typeName = string.Format("Clients.{0}, {0}", clientName);
Type clientType = Type.GetType(typeName);
IClientPlugin clientPluginInstance =
(IClientPlugin)Activator.CreateInstance(clientType);
return clientPluginInstance;
}
EDIT
If your plugin classes are located in the same assembly as your main project, you can simplify the call of Type.GetType to just specify the classname:
Type.GetType(clientName);
var myClient = Activator.CreateComInstanceFrom("Acme.dll","Acme");
Where you can parametrize the Assembly name and the type name.

Missing object properties from a WCF service with SubSonic?

I have written a basic WCF service that uses SubSonic for data retrieval.
After publishing the service I am consuming it in a C# application. When calling the method that uses that SubSonic query, I get back the right number of objects from the database, but none of them contain the database properties and their values. It looks like only SubSonic properties.
The SubSonic DAL is contained in a separate project that is referenced in the WCF service project.
WCF service interface:
[OperationContract]
GeoLocationCollection GetGeoLocations(long websiteID);
Worker method:
public GeoLocationCollection GetWebsiteGeoLocations(long websiteID)
{
GeoLocationCollection locationsCollection = new Select()
.Where(GeoLocation.Columns.WebsiteID).IsEqualTo(1)
.From(GeoLocation.Schema)
.ExecuteAsCollection<GeoLocationCollection>();
return locationsCollection;
}
Both the GeoLocationCollection and GeoLocation have been automatically decorated with [Serializable].
The service is consumed as follows:
MyService.MyServiceClient client = new MyService.MyServiceClient();
var result = client.GetWebsiteGeoLocations(1);
foreach (MyService.GeoLocation location in result)
{
// do stuff
}
So once again, why can I not see any of my actual table properties/values in location?
WCF services require [DataContract] + [DataMember] attribute and not [Serializable]. This maybe the reason for you to not get the attribute values.

Passing environment variables to Data Access Layer

Every stored procedure we write has to have clientip, serverip, windows username, etc passed on to it.
The question is how do I efficiently pass these to DAL?
I'm assuming this is a web app in ASP.NET. If that's the case, you have access to all these things in the context of a web request outside of the web application through the following static instance:
System.Web.HttpContext.Current
If everything you need is standard stuff that you usually have in the Request, Response, and User objects that are available by default at the Page level, then this should be all you need. If you need information that is custom to your web app, then Ben's answer (above) should work.
You should have all of the above data accessible either in the System.Environment class, or in your own Thread Principal of some kind. Your DAL can easily pull in from both or either of those sources.
Create a class to hold this data, a factory to build it and helper methods to consume it.
IUserContext
{
int param1 {get;set;}
int param2 {get;set;}
SqlParameter[] GetSqlParameters();
}
UserContext : IUserContext{}
UserContextFactory
{
internal IUserContext IUserContextFromRequest(){}
}
Good luck

Categories

Resources