WCF Services using same entity model class but exposes different in client - asp.net

I am new to WCF Services and can't get rid of this problem. For the next version of our web application I want to make use of WCF as webservice. Currently I am stuck with this problem:
To try WCF out I made 2 services: EmployeeService and AuthenticationService. I also made a datacontract Employee.
In AuthenticationService I use EmployeeService to get the logged Employee
Now in my client (ASP MVC Web) I add both Services as I need them both. But then when I try to use the object Employee I get the error :
Employee' is an ambiguous reference between 'IWA.Portal.AuthenticationService.Employee' and 'IWA.Portal.EmployeeService.Employee
The reason I want to make multiple services is to group them functionally. Example: Everything regarding employees will be under EmployeeService and everything regarding job will be under JobService.
How can I fix this or how should I structure my webservice?
Currently my webservice solution consists of :
Project.DataContracts (Entities)
Project.ServiceContracts (Interfaces)
Project.Services (Services, NHibernate & Castle Windsor)
Any help is much appreciated! Thx
AuthenticationService
public class AuthenticationService : IAuthenticationService
{
private readonly IEmployeeService _employeeService;
public AuthenticationService(IEmployeeService employeeService)
{
_employeeService = employeeService;
}
public Employee Authenticate()
{
var employee = _employeeService.Get(1);
return employee;
}
}
Code in my client (Controller)
readonly EmployeeServiceClient _employeeService = new EmployeeServiceClient();
readonly AuthenticationServiceClient _authenticationService = new AuthenticationServiceClient();
Employee authedEmployee = _authenticationService.Authenticate();
Employee test = _employeeService.Get(827);

Looks like your namespaces are clashing and to fix it you will need to use full names in your code when referring to a class so instead of just Employee use
AuthenticationService.Employee auth_emp = new AuthenticationService.Employee();
and
EmployeeService.Employee es_emp = new EmployeeService.Employee();
This will solve your problem.

Related

Azure Table Storage best practice for ASP.NET MVC/WebApi

What are the best practices for connecting to a Azure Table Storage from a ASP.NET MVC or Web API app?
Right now I've made a StorageContext class which holds a reference to the CloudStorageAccount and CloudTableClient, like this:
public class StorageContext
{
private static CloudStorageAccount _storageAccount;
private static CloudTableClient _tableClient;
public StorageContext() : this("StorageConnectionString") { }
public StorageContext(string connectionString)
{
if (_storageAccount == null)
_storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings[connectionString].ConnectionString);
if (_tableClient == null)
_tableClient = _storageAccount.CreateCloudTableClient();
}
public CloudTable Table(string tableName)
{
var table = _tableClient.GetTableReference(tableName);
table.CreateIfNotExists();
return table;
}
}
And my controller I'm using it like this:
public class HomeController : ApiController
{
private StorageContext db;
public HomeController() : this(new StorageContext()) { }
public HomeController(StorageContext context)
{
this.db = context;
}
public IHttpActionResult Get()
{
var table = db.Table("users");
var results = (from user in table.CreateQuery<User>()
select user).Take(10).ToList();
return Ok<List<User>>(results);
}
}
Is this the preferred way of doing it?
The API is going to be used on a high traffic site with > 1000 req/sec.
I also need unit tests. Using it like above it I can pass in another connString name and instead connect to the Azure Storage emulator in my unit tests.
Am I on the right track or are there better ways to connect?
Actually your question
What are the best practices for connecting to a Azure Table Storage
from a ASP.NET MVC or Web API app?
could be restated like "What are the best practices to use data access layer in web application". It is the same.
You can find a lot of answers about data access layer best practices. But iron rule here keep your data access layer separated from your controller or presentation. The best way to use it through Model in scope of MVC pattern, or you can think about Repository and/or Unit of work pattern if you like them.
In your example your data access logic is already wrapped in StorageContext, which is fine, I would additionally extract interface and use DI/IoC and dependency resolver for it. That's all when speaking about your code snippet. You are on right way.

MVC Custom Membership and Role Provider context lifetime issue

I'm having problems with custom membership within MVC 4 I keep getting a context lifetime related error when I do a ajax call to get a partial result from the server(controller), the error is always {"The provider has been closed"} or {"There is already an open DataReader associated with this Command which must be closed first."} the error always lands within the custom RoleProvider.
I will try to explain the current setup im using.
I have inherited from the Membership and RoleProvier and overridden all the methods like so
public class CustomRoleProvider : RoleProvider
{
private IAccountService _accountService;
public CustomRoleProvider()
{
_accountService = new AccountService();
}
public override string[] GetRolesForUser(string username)
{
return _accountService.GetRolesForUser(username);
}
}
The Membership provider is implemented in the same way the IAccountService above is the service layer that deals with all user accounts & roles all the service layer classes implement a base service class called ServiceBase that creates the DB context
public class ServiceBase
{
protected Context Context;
protected ServiceBase() : this("Context") {}
protected ServiceBase(string dbName)
{
IDatabaseInitializer<Context> initializer = new DbInitialiser();
Database.SetInitializer(initializer);
Context = new Context(dbName);
}
}
The Controller that has the ajax to made to it
[Authorize(Roles = "Administrator,Supplier")]
public class AuctionController : Controller
{
private IAuctionService _service;
public AuctionController()
{
_service = new AuctionService();
}
public AuctionController(IAuctionService service)
{
_service = service;
}
[CacheControl(HttpCacheability.NoCache), HttpGet]
public ActionResult RefreshAuctionTimes(int auctionId)
{
return PartialView("_AuctionTimer", BusinessLogic.Map.ConvertAuction(_service.GetAuction (auctionId)));
}
}
The problem only started when I added the [Authorize(Roles = "Administrator,Supplier")] attribute to the controller that handled the ajax call, I know this is the lifetime of the DbContext being for the life of the app and the controllers service layer being destroyed and recreated on every post but I'm not sure of the best way to handle this, I have used this setup before but with DI and Windsor and never had this problem as the IOC was controlling the context.
Would it be best to create the providers its own DB context or is the conflict between the 2 providers and really they need to share the same db context?
Any help would be great thanks
The problem is exactly what you're suspecting. Is due to the fact that you're creating a single instance of the DbContext and therefore you're having connection issues. If you use it with an IOC/DI schema, you're going to fix it. The other option is to manually handle the connections.
An example of how to do this using Ninject as IOC container is here
They need to share the same context in order for the problem to stop.
I would suggest you create your service layer class on each call to GetRolesForUser:
public override string[] GetRolesForUser(string username)
{
return new AccountService().GetRolesForUser(username);
}

How to obtain a list of Users from ASP.NET Identity?

Edit: This question is outdated
The Identity Framework was a moving target at the moment I asked this. The authors changed quite a few things and they have decoupled several others, making everything easier.
Have a look at the Asp.NET Identity Sample project on github.
I'm creating a small application that requires user management. Registration is not allowed, instead there is a super user that will create and modify login information.
I'm using the new ASP.NET Identity membership system, and sure enough, creating users and adding roles is easy and intuitive.
Now, my question: How to obtain a list of users using the AuthenticationIdentityManager class that is used by the generated AccountController class? I couldn't find a way to access the user list from my controller.
(By the way, the new name "Identity" may sound awesome to some people but it is a pain to search for.)
Edit: If I try to do this
ApplicationDbContext UsersContext = new ApplicationDbContext();
UsersContext.Users.ToList(); // Exception
I get an exception Invalid column name 'Discriminator'. The definition of ApplicationDbContext is generated automatically by the new application wizard:
using Microsoft.AspNet.Identity.EntityFramework;
namespace Cobranzas.Models
{
public class ApplicationUser : User
{
}
public class ApplicationDbContext : IdentityDbContextWithCustomUser<ApplicationUser>
{
}
}
So my guess is that Discriminator column is for telling apart ApplicationUser from User. However, it does not exists in my database (which was created automatically by the application.)
I found out that I wasn't using the derived ApplicationUser object for anything, so I just went ahead and changed all uses of it for plain old User. Then I just changed ApplicationDbContext definition for the following:
public class ApplicationDbContext : IdentityDbContext<
User, UserClaim, UserSecret, UserLogin,
Role, UserRole, Token, UserManagement>
{
}
And now I can access the user list:
UsersContext = new ApplicationDbContext();
...
UsersContext.Users.ToList();
However, I think this will come back and haunt me in the future (I'll probably need to add more fields to User) so probably I'll have to use the same approach as in this question:
Get all role names in ASP.NET MVC5 Identity system
Edit: Since I got the need to add a new property, I had to revert my changes. So I went ahead and did a line by line comparison with the ASP.NET Identity Sample Project, and found out that the generated project had the following line:
IdentityManager = new AuthenticationIdentityManager(new IdentityStore());
while the Sample application had included the database context in the constructor. So I added it in my constructor, recreated the database and the problem went away.
IdentityManager = new AuthenticationIdentityManager(new IdentityStore(new ApplicationDbContext()));
Create ASP .NET MVC5 project by default
Create ASP .NET Identity tables properly and change connection string as well.
To get users just do the following test
A. Go to AccountController
B. Create any dummy method and put there
var context = new ApplicationDbContext();
var allUsers = context.Users.ToList();
For RTM, you will have to drop down to your DbContext or whatever your specific store implementation has to enumerate all users. In the next release, we will most likely be adding an optional IQueryable Users/Roles method on the Manager classes that stores can implement to expose IQueryables for both users and stores.
using System.Linq;
using System.Data;
using System.Data.Entity;
var db = new ApplicationDbContext();
var Users = db.Users.Include(u => u.Roles);
If we can use the following type of Constructor in Identity AccountController.
public AccountController(ApplicationUserManager userManager,
ISecureDataFormat<AuthenticationTicket> accessTokenFormat)
{
UserManager = userManager;
AccessTokenFormat = accessTokenFormat;
}
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
then we can directly used UserManager object to get user list like
var userList= UserManager.Users.ToList();
You can do this by explicitly setting right types:
var userStore = new UserStore<IdentityUser>();
var userManager = new UserManager<IdentityUser>(userStore);
IQueryable<IdentityUser> usersQuery = userManager.Users;
List<IdentityUser> users = usersQuery.ToList();
Imoports:
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using System.Linq;
using System.Collections.Generic;

Attach additional ObjectSets to ObjectContext from separate project

I hope this makes sense. I have a ASP.NET web application that uses Entity Framework. I have added a couple of custom tables to the db and created a separate project to handle the CRUD operations for those tables. I chose the separate project because I don't want future upgrades to the application to overwrite my custom features.
My problem is this. How do I attach/combine my custom ObjectContext to the ObjectContext of the application? I want to use the same UnitOfWorkScope (already in the application) to maintain the one ObjectContext instance per HTTP request. Again, I don't want to add my ObjectSets to the application's ObjectContext for my reason listed above.
Here is some code:
Widget.cs
public partial class Widget
{
public Widget()
{
}
public int WidgetId {get;set;}
public string WidgetName {get;set;}
}
WidgetObjectContext.cs
public partial class WidgetObjectContext : ObjectContext
{
private readonly Dictionary<Type, object> _entitySets;
public ObjectSet<T> EntitySet<T>()
where T : BaseEntity
{
var t = typeof(T);
object match;
if(!_entitySets.TryGetValue(t, out match))
{
match = CreateObjectSet<T>();
_entitySets.Add(t, match);
}
return (ObjectSet<T>)match;
}
public ObjectSet<Widget> Widgets
{
get
{
if((_widgets == null))
{
_widgets = CreateObjectSet<Widget>();
}
return _widget;
}
}
private ObjectSet<Widget> _widgets;
In my WidgetManager class if I was using the application's ObjectContext I would query my tables like this:
var context = ObjectContextHelper.CurrentObjectContext;
var query = from c in context.ObjectSet .... etc
What I want would be to do something like this:
var context = ObjectContextHelper.CurrentObjectContext.Attach(WidgetObjectContext);
I know this won't work but that is the gist of what I am trying to accomplish. Hope this is clear enough. Thanks.
I don't think it is possible. ObjectContext creates entity connection which connects to metadata describing mapping and database. But you have to different sets of metadata - one for ASP.NET application and one for separate project. Simply you need two connection to work with these models => you need two ObjectContexts.
FYI: The previous answer was correct at the time of the answer. It is now possible to do this using the DbContext available in EF 4.1. The caveat is that you must use the code-first strategy in order to build your custom context. In other words, you won't be able to use EDMX files to accomplish this.

ASP.NET MVC design

As I've stated before I'm working on a digg clone to teach myself ASP.NET MVC Inside and out but I've hit a road bump that I can't seem to avoid.
I want to be able to optimize this application as much as possible so I have my DAL which is a bunch of classes of ...Repository : Repository. Now to help optimize for performance I have my base repository classes return my ViewData objects so that they can select extra fields needed without having to create an anonymous type.
Stories have Users who have created them and Users have Votes for Stories. Pretty easy DB layout. Now I handle my own membership because the default ASP.NET membership is so bloated. In my view for the list of stories I have to determine if the current user has voted on the story being rendered. Now since I figured data access in the View shouldn't be happening it should be in either my controller or my DAL. Since I'm already returning ViewData from my DAL i added another property on the StoryViewData type named "UserVotedOn" that returns true if the user has voted on that story.
Problem with this is I have to either A) make the DAL aware of membership or B) pass in the User ID into the query methods on the DAL. Neither of these feel right to me and I'm looking for some good solutions. Any feedback is welcome.
In my MVC apps I'm using architecture that Rob Conery showed on his MVC Storefront video series and it works like charm for me.
Repository => Service + Filters => Controller => View
I've tried to simulate what you want to achieve and managed todo like this
Edit1: Changed IList to IQueryable in repository and filters
Repository
public interface IRepository
{
IQueryable<Vote> GetVotes();
IQueryable<Story> GetStories();
}
Service for getting what you want
public class Service : IService
{
private IRepository _repository;
public Service(IRepository repository)
{
_repository = repository;
if (_repository == null) throw new InvalidOperationException("Repository cannot be null");
}
public IList<Vote> GetUserVotes(int userID)
{
return _repository.GetVotes().WithUserID(userID).ToList();
}
public IList<Story> GetNotVotedStories(IList<Vote> votes)
{
return _repository.GetStories().WithoutVotes(votes).ToList();
}
}
Filters to filter your stories and user votes (These are basically extension methods). Not the nicest implementation out there, but you can rewrite later
public static class Filters
{
public static IQueryable<Vote> WithUserID(this IQueryable <Vote> qry, int userID)
{
return from c in qry
where c.UserID == userID
select c;
}
public static IQueryable<Story> WithoutVotes(this IQueryable <Story> qry, IList <Vote> votes)
{
return from c in qry
where votes.Where(x => x.StoryID == c.StoryID).ToList().Count > 0
select c;
}
}
And then you can pass current UserID in controller, not in DAL or View like you had to do before
public class HomeController : Controller
{
private readonly IRepository _repository;
private readonly IService _service;
public HomeController()
{
_repository = new Repository();
_service = new Service.Service(_repository);
}
public ActionResult Index()
{
var userVotes = _service.GetUserVotes(CurrentUserID);
var unvotedStories = _service.GetNotVotedStories(userVotes);
return View(unvotedStories);
}
}
This allows you to stay away from adding user related UserVotedOn property to your Story model
It looks like you're missing the BLL.
Actually, the right architecture of an MVC application is what many people still trying to figure out.
I personally consider UserID to be somewhat a translayer concept. It will appear on both DAL and BLL levels.
Basically, your controller method should have just a few very basic calls to the BLL, only to determine how to react to user input, whether to return on view or another.
Your view should only deal with model objects. A model should probably be filled by the business logic. You could call BL methods in a controller method in order to initialize you model object and then pass it to the view.
Controller should not communicate directly with the database. Neither should it probably deal with low level objects which comprise your domain objects and models.
P.S. i would try to avoid extensive use of ViewData. Strongly-typed model classes are a much better option. You can also group them in hierarchies to inherit some common properties. Just like your domain model classes could derive from a base class that has a UserID property defined.

Resources