Third Party Authentication Oauth with Adapter Pattern Design - c#

I am writing a third party authentication method for facebook and google+ currently.
I decided to use adapter design pattern and this is my first time that I am following design patterns
Here is my design structure
namespace ThirdPartyRegister.Tests
{
[TestClass]
public class ThirdPartyRegister
{
[TestMethod]
public void Login_Test()
{
IThirdPartyAuthenticationAdapter adapter= new ThirdPartyAuthenticationAdapter(new GooglePlusAuthentication());
var testResult = adapter.Login();
Assert.IsFalse(testResult);
}
}
public interface IThirdPartyAuthenticationAdapter{
bool Login();
}
public class ThirdPartyAuthenticationAdapter : IThirdPartyAuthenticationAdapter
{
private readonly IThirdPartyAuthenticationAdapter _thirdPartyAuthentication;
public ThirdPartyAuthenticationAdapter (IThirdPartyAuthenticationAdapter thirdPartyAuthentication){
_thirdPartyAuthentication = thirdPartyAuthentication;
}
public bool Login()
{
return _thirdPartyAuthentication.Login();
}
}
public class GooglePlusAuthentication : IThirdPartyAuthenticationAdapter{
public bool Login()
{
return false;
}
}
public class FacebookAuthentication : IThirdPartyAuthenticationAdapter{
public bool Login()
{
return true;
}
}
}
My question is the approach applied above proper? Or did I miss something for adapter design pattern

Related

Sequence contains no matching element error when returning class Type of Interface using IsAssignableFrom

This is a follow up question to another post I created around implementing a UI test solution that could toggle which classes to execute code from based on interfaces. The whole goal was to re use test code on versions of apps that are identical (Web vs WPF).
The code compiles fine, but after the test is ran it bombs out on the GetPageModelType method call. Below is my implementation pretty much identical to the linked post, with a few minor adjustments to abstract some of the page object creation on a TestClassBase
UI Test that can determine which classes to execute code from at runtime using interfaces
Interface and corresponding Page Object classes
public interface ILogin
{
void Login(string username, string password);
}
public class WebLogin : ILogin
{
private readonly IWebDriver driver;
public WebLogin(IWebDriver driver)
{
this.driver = driver;
}
public void Login(string username, string password)
{
Console.WriteLine("Web Success!");
}
}
public class WPFLogin : ILogin
{
private readonly WindowsDriver<WindowsElement> session;
public WPFLogin(WindowsDriver<WindowsElement> session)
{
this.session = session;
}
public void Login(string username, string password)
{
Console.WriteLine("WPF Success!");
}
}
Page Object factory classes
public interface IPageModelFactory
{
ILogin CreateLogin();
}
public class WebPageModelFactory : IPageModelFactory
{
private readonly IWebDriver driver;
public WebPageModelFactory(IWebDriver driver)
{
this.driver = driver;
}
public ILogin CreateLogin()
{
return new WebLogin(driver);
}
}
public class WPFPageModelFactory : IPageModelFactory
{
private readonly WindowsDriver<WindowsElement> session;
public WPFPageModelFactory(WindowsDriver<WindowsElement> session)
{
this.session = session;
}
public ILogin CreateLogin()
{
return new WPFLogin(session);
}
}
public class PageModelFactory
{
private readonly object client;
public PageModelFactory(object client)
{
this.client = client;
}
// Create Page Objects
public ILogin CreateLoginPage()
{
var pageModelType = GetPageModelType<ILogin>();
var constructor = pageModelType.GetConstructor(new Type[] { client.GetType() });
return (ILogin)constructor.Invoke(new object[] { client });
}
private Type GetPageModelType<TPageModelInterface>()
{
return client.GetType().Assembly.GetTypes().Single(type => type.IsClass && typeof(TPageModelInterface).IsAssignableFrom(type));
}
}
TestClassBase - base class for tests, simplifies test scripts
[TestFixture]
public class TestClassBase
{
// WinAppDriver variables
private static string WinAppDriverExe = "C:\\Program Files (x86)\\Windows Application Driver\\WinAppDriver.exe";
private string WindowsApplicationDriverUrl = "http://127.0.0.1:4723";
// Sessions
public WindowsDriver<WindowsElement> session;
public IWebDriver driver;
// Declare Page Objects
public ILogin login = null;
[SetUp]
public void SetUp()
{
if (GlobalData.targetHost.Equals("WPF"))
{
// Capabilities
AppiumOptions appCapabilities = new AppiumOptions();
appCapabilities.AddAdditionalCapability("app", GetExeFile());
appCapabilities.AddAdditionalCapability("appWorkingDir", GetWorkingDirectory());
// Create Session
session = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), appCapabilities, TimeSpan.FromMinutes(3));
session.Manage().Window.Maximize();
// Pass session to page objects
PageModelFactory wpfPages = new PageModelFactory(session);
login = wpfPages.CreateLoginPage();
} else if (GlobalData.targetHost.Equals("Web"))
{
}
}
[TearDown]
public void TearDown()
{
// Clean up code...
}
}
LoginTests
public class LoginTests : TestClassBase
{
[Test]
public void Login()
{
// Login
login.Login("", "");
}
}
Whats not pictured above is my GlobalData.cs class which just contains a bunch of hardcoded variables that are used in the tests. I have the targetHost variable set to "WPF" while testing this against the WPF host. The StartUp code does launch the app as expected, it fails when we call GetPageModelType on PageModelFactory.CreateLoginPage();
I wasn't able to see this in my answer on your original question. The assembly in which the "client" resides and the assembly in which the page models reside are different. That means the PageModelFactory will need a second constructor parameter to know which assembly to search when initializing new page models:
public class PageModelFactory
{
private readonly object client;
private Assembly Assembly => GetType().Assembly;
public PageModelFactory(object client)
{
this.client = client;
}
// Create Page Objects
public ILogin CreateLoginPage()
{
var pageModelTypes = GetPageModelTypes<ILogin>();
var constructorSignature = new Type[] { client.GetType() };
foreach (var type in pageModelTypes)
{
var constructor = type.GetConstructor(constructorSignature);
if (constructor != null)
return (ILogin)constructor.Invoke(new object[] { client });
}
throw new InvalidOperationException($"No class found implementing ILogin with a constructor that accepts {client.GetType().FullName} as an argument in assembly {Assembly.Name}");
}
private IEnumerable<Type> GetPageModelTypes<TPageModelInterface>()
{
return Assembly.GetTypes()
.Where(type => type.IsClass
&& typeof(TPageModelInterface).IsAssignableFrom(type));
}
}

C# Interface? categories methods with the same name

how to do something like this. So the scenario is I have 2 "DoLogin" methods in a different platform (Mobile Version, Desktop Version)
I want to make the code more readable and look something like this
Ex.
if I wanted to login to a desktop version.
webDriver.Desktop.Dologin(accountModel)
If I wanted to login to a mobile version.
webDriver.Mobile.DoLogin(accountModel)
this is what I currently have.
public static class Desktop
{
public static void DoLogin(this ChromeDriver webDriver, AccountModel account)
{
}
}
public static class Mobile
{
public static void DoLogin(this ChromeDriver webDriver, AccountModel account)
{
}
}
EDIT
This is what I'm currently doing to organize it.
public static class Desktop
{
public static void DesktopDoLogin(this ChromeDriver webDriver, AccountModel account)
{
}
}
public static class Mobile
{
public static void MobileDoLogin(this ChromeDriver webDriver, AccountModel account)
{
}
}
whenever I call a method let say desktop what I do is.
webDriver.DesktopDoLogin(account)
or
webDriver.MobileDoLogin(account)
I guess whats important is it works.
I personally don't like using extension methods. This is a preference. I would have most likely implemented it as follows. I have never used Selenium before, so I'm not sure what interface WebDriver is/implements but you can get the gist of the pattern.
public interface IPlatform
{
void Login<T>(T model);
}
public class Desktop : IPlatform
{
private readonly WebDriver _webDriver;
public Desktop(WebDriver driver)
{
_webDriver = driver;
}
public void Login<T>(T model)
{
// do login here
}
}
// usage
IPlatform desktop = new Desktop(/*chromedriver*/); // or inject
desktop.Login<AccountModel>(model);
It seems to me that you can get this:
void Main()
{
var webDriver = new ChromeDriver();
webDriver.Desktop.DoLogin(new AccountModel());
webDriver.Mobile.DoLogin(new AccountModel());
}
By doing this:
public interface IDoLogin
{
void DoLogin(AccountModel account);
}
public class Desktop : IDoLogin
{
private ChromeDriver _webDriver;
public Desktop(ChromeDriver webDriver)
{
_webDriver = webDriver;
}
public void DoLogin(AccountModel account) { }
}
public class Mobile : IDoLogin
{
private ChromeDriver _webDriver;
public Mobile(ChromeDriver webDriver)
{
_webDriver = webDriver;
}
public void DoLogin(AccountModel account) { }
}
public class ChromeDriver
{
public Desktop Desktop;
public Mobile Mobile;
public ChromeDriver()
{
this.Desktop = new Desktop(this);
this.Mobile = new Mobile(this);
}
}
You can do it easily using some static voids like that:-
Public class desktop {
Public static void DoLogin(AccountModel val){
//code for desktop
}
}
Public class mobile {
Public static void DoLogin(AccountModel val){
//code for mobile
}
}
Public class webDriver{
Public static desktop Desktop;
Public static mobile Mobile;
}
//usage
webDriver.mobile.DoLogin(...);
//or
mobile.DoLogin();
Why not using Interface?
Create one common interface with DoLogin Method, and Implement that interface in Desktop and Mobile class.
Common Interface:
public interface ICommon
{
void Login<T>(T model);
}
Implement this interface in your Desktop and Mobile Class.

HttpContext(User.Identity) in Controller (asp web api) not working

I have some problems with correctly working HttpContext.Current.User.Identity. From Controller constructor this doesn't work, I have to implement this to some method. Look at this example.
public class SomeControler : ApiController
{
private UserData userData;
// NOT WORKING
public ChartsController(
RegisteredUserData registeredUserData,
NotLoggedInUserData NotLoggedInUserData
{
var isAuthenticated = HttpContext.Current.User.Identity.IsAuthenticated;
this.userData = isAuthenticated
? (IUserData)registeredUserData
: (IUserData)NotLoggedInUserData;
}
// WORKING
public SomeMethod(
RegisteredUserData registeredUserData,
NotLoggedInUserData NotLoggedInUserData
{
var isAuthenticated = HttpContext.Current.User.Identity.IsAuthenticated;
this.userData = isAuthenticated
? (IUserData)registeredUserData
: (IUserData)NotLoggedInUserData;
}
}
How I can fix this? I spent a lot of time for answer in web but i didnt get this.
Regards.
edit
I found an answer. Is it good solution ?
public class SomeControler : ApiController
{
private RegisteredUserData registeredUserData;
private NotLoggedInUserData notLoggedInUserData;
private UserData userData
{
get
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
return registeredUserData;
}
return notLoggedInUserData;
}
}
public ChartsController(
RegisteredUserData registeredUserData,
NotLoggedInUserData notLoggedInUserData
{
this.registeredUserData = registeredUserData;
this.notLoggedInUserData = notLoggedInUserData;
}
}
First, the request and HttpContext is not available yet in the construct of the controller because of where in the request flow the controller is initialized. You have to access it in an action where by then, the request and context would have been fully realized.
Next do not couple your controllers to HttpContext. It makes your code difficult to test and maintain.
Extract the desired information in a service abstraction.
public interface IUserDataAccessor {
IUserData UserData { get; }
}
public class UserDataAccessor : IUserDataAccessor {
private readonly RegisteredUserData registeredUserData;
private readonly NotLoggedInUserData notLoggedInUserData;
public UserDataAccessor(
RegisteredUserData registeredUserData,
NotLoggedInUserData notLoggedInUserData) {
this.registeredUserData = registeredUserData;
this.notLoggedInUserData = notLoggedInUserData;
}
public IUserData UserData {
get {
if (HttpContext.Current?.User?.Identity?.IsAuthenticated) {
return registeredUserData;
}
return notLoggedInUserData;
}
}
}
This allows the controller to remain lean with just the dependency on the abstraction.
public class ChartsController : ApiController {
private readonly IUserDataAccessor accessor;
public ChartsController(IUserDataAccessor accessor) {
this.accessor = accessor;
}
[HttpGet]
public IHttpActionResult SomeAction() {
var userData = accessor.UserData;
//...do something associated with user data
return OK();
}
}
Finally make sure that the abstraction and it's implementation a registered with your dependency container in your composition root.

How to manage lifecycle of WCF clients in a WPF application [duplicate]

This question already has answers here:
Dependency Injection wcf
(2 answers)
Closed 6 years ago.
In developing a WPF application that allows editing of article and carrier (pallet, racking) data (in a CRUD-fashion) I'm looking how to manage the lifecycle of the WCF clients connecting to the service that contains the actual data.
I prefer to use an MVVM approach using Caliburn Micro and StructureMap or Castle Windsor.
My main issue is not the creation of WCF client channels or factories, but more important the cleanup after use. I intend to use per-request lifecycle on the server side, as such I will need to create and dispose my clients on a per-request basis. As such I have the following in mind:
public class Article
{
public int Id { get; set; }
public string ArticleId { get; set; }
}
[ServiceContract]
public interface IArticleCrud
{
[OperationContract]
Article CreateArticle(string articleId);
[OperationContract]
void Delete(int articleId);
}
public class ArticlesViewModel
{
private readonly Func<IArticleCrud> articleCrudFactory;
public ArticlesViewModel(Func<IArticleCrud> articleCrudFactory)
{
this.articleCrudFactory = articleCrudFactory;
}
public void Delete(int articleId)
{
// Doesn't work since IArticleCrud is not IDisposable
using (var crud = articleCrudFactory())
{
crud.Delete(articleId);
}
}
}
As noted in the comment this won't work because IArticleCrud is not IDisposable. IArticleCrud is used to create a ChannelFactory on the client side to generate proxies for the service implementing the same interface. I'd happily swap out this code for the following:
public class DeleteArticleCommand : IRequest
{
public int Id { get; set; }
}
public class ArticlesViewModel
{
private readonly IMediator mediator;
public ArticlesViewModel(IMediator mediator)
{
this.mediator = mediator;
}
public void Delete(int articleId)
{
mediator.Send(new DeleteArticleCommand {Id = articleId});
}
}
public class DeleteArticleCommandHandler : RequestHandler<DeleteArticleCommand>
{
private readonly IArticleCrud articleCrud;
public DeleteArticleCommandHandler(IArticleCrud articleCrud)
{
this.articleCrud = articleCrud;
}
protected override void HandleCore(DeleteArticleCommand message)
{
articleCrud.Delete(message.Id);
}
}
However, this doesn't solve my problem as I'm still not dealing with the disposal of the WCF client. I could however make the IMediator create a new nested container on the Send action and have it disposed after the Send action completes, but it seems like a lot of hassle.
Am I getting it all wrong, or does it just require a lot of effort just to perform a WCF call from a WPF application?
As a sidenote, I will be having more services than just these few CRUD services, so the perhaps pragmatic solution of fixing this in my CRUD services is not an option.
I've dealt with the same Problem (WCF-Service used in a WPF Application) and wanted to use the ServiceInterface instead the ServiceClient (which is IDisposable and can be used in a using-block).
One of the solutions to Close the Connection is to cast the Interface to the Client-type and call the .Close()-Method:
public class Article
{
public int Id { get; set; }
public string ArticleId { get; set; }
}
public interface IArticleCrud
{
Article CreateArticle(string articleId);
void Delete(int articleId);
}
public class ArticlesViewModel
{
private readonly Func<IArticleCrud> articleCrudFactory;
public ArticlesViewModel(Func<IArticleCrud> articleCrudFactory)
{
this.articleCrudFactory = articleCrudFactory;
}
public void Delete(int articleId)
{
//Using-Block doesn't work since IArticleCrud is not IDisposable
var crud = articleCrudFactory();
crud.Delete(articleId);
if (crud is ArticleCrud)
(crud as ArticleCrud).Close();
}
}
You can also create a static method in your articleCrudFactory that will Close your IArticleCrud:
public static void CloseInterface(IArticleCrud crud)
{
if (crud is ArticleCrud)
(crud as ArticleCrud).Close();
else { ... }
}
I've done it already with WCF and MVVM and its really easy (if I get your problem right):
public interface IRequest
{
}
public interface IRequestHandler<in TCommand> where TCommand : IRequest
{
void HandleCore(TCommand command);
}
public class DeleteArticleCommand : IRequest
{
public int Id { get; set; }
}
public class ArticlesViewModel
{
private readonly IRequestHandler<DeleteArticleCommand> _handler;
public ArticlesViewModel(IRequestHandler<DeleteArticleCommand> handler)
{
_handler = handler;
}
public void Delete(int articleId)
{
_handler.HandleCore(new DeleteArticleCommand { Id = articleId });
}
}
//On client side
public sealed class WcfServiceCommandHandlerProxy<TCommand>
: IRequestHandler<TCommand> where TCommand : IRequest
{
public void HandleCore(TCommand command)
{
using (var service = new ActuaclWcfServiceClient())
{
service.Send(command); //Or however you are working with you WCF client
}
}
}
//Somewhere on server side
public class DeleteArticleCommandHandler : IRequestHandler<DeleteArticleCommand>
{
private readonly IArticleCrud _articleCrud;
public DeleteArticleCommandHandler(IArticleCrud articleCrud)
{
_articleCrud = articleCrud;
}
public void HandleCore(DeleteArticleCommand message)
{
articleCrud.Delete(message.Id);
}
}
Just register your IRequestHandler interface to be implemented with WcfServiceCommandHandlerProxy type and that's it:
//May vary :)
Register(typeof (ICommandHandler<>), typeof (WcfServiceCommandHandlerProxy<>))

Validation Using service layer in mvc 4 to achieve server side and client side validation

Hi I have table employee with some fields
to validate fields I have created two layers
Service layer
Employee repository
Employee repository code is
namespace MvcApplication2.Models
{
public interface IEmployeeMainTableRepository
{
bool CreateEmployee(EMP_MAIN_TBL EmployeeToCreate);
IEnumerable<EMP_MAIN_TBL> ListEmployees();
}
public class EmployeeRepository : MvcApplication2.Models.IEmployeeMainTableRepository
{
private EMPLOYEE_SYSTEMEntities _entities = new EMPLOYEE_SYSTEMEntities();
public IEnumerable<EMP_MAIN_TBL> ListEmployees()
{
return _entities.EMP_MAIN_TBL.ToList();
}
public bool CreateEmployee(EMP_MAIN_TBL EmployeeToCreate)
{
try
{
// _entities.AddToEMP_MAIN_TBL(productToCreate);
_entities.SaveChanges();
return true;
}
catch
{
return false;
}
}
}
And service layer contains
public interface IEmployeeService
{
bool CreateEmployee(EMP_MAIN_TBL EmployeeToCreate);
System.Collections.Generic.IEnumerable<EMP_MAIN_TBL> ListEmployees();
}
public class EmployeeService : MvcApplication2.Models.IEmployeeService
{
private IValidationDictionary _validatonDictionary;
private IEmployeeMainTableRepository _repository;
public EmployeeService(IValidationDictionary validationDictionary, IEmployeeMainTableRepository repository)
{
_validatonDictionary = validationDictionary;
_repository = repository;
}
protected bool ValidateEmployee(EMP_MAIN_TBL employeeToValidate)
{
if (employeeToValidate.EMP_NM == null)
_validatonDictionary.AddError("EMP_NM", "Name is required.");
if (employeeToValidate.PLCE_OF_BRTH == null)
_validatonDictionary.AddError("PLCE_OF_BRTH", "Place of birth is required.");
return _validatonDictionary.IsValid;
}
public IEnumerable<EMP_MAIN_TBL> ListEmployees()
{
return _repository.ListEmployees();
}
public bool CreateEmployee(EMP_MAIN_TBL EmployeeToCreate)
{
// Validation logic
if (!ValidateEmployee(EmployeeToCreate))
return false;
// Database logic
try
{
_repository.CreateEmployee(EmployeeToCreate);
}
catch
{
return false;
}
return true;
}
and I have created two more classes to add validation messages
public interface IValidationDictionary
{
void AddError(string key, string errorMessage);
bool IsValid { get; }
}
And
public class ModelStateWrapper : IValidationDictionary
{
private ModelStateDictionary _modelState;
public ModelStateWrapper(ModelStateDictionary modelState)
{
_modelState = modelState;
}
#region IValidationDictionary Members
public void AddError(string key, string errorMessage)
{
_modelState.AddModelError(key, errorMessage);
}
public bool IsValid
{
get { return _modelState.IsValid; }
}
#endregion
}
finally employee controllers contains below structure
public class EmployeeController : Controller
{
private IEmployeeService _service;
public EmployeeController()
{
_service = new EmployeeService(new ModelStateWrapper(this.ModelState), new EmployeeRepository());
}
public EmployeeController(IEmployeeService service)
{
_service = service;
}
public ActionResult Index()
{
return View(_service.ListEmployees());
}
//
// GET: /Product/Create
public ActionResult Create()
{
return View(new EMP_MAIN_TBL());
}
//
// POST: /Product/Create
[AcceptVerbs(HttpVerbs.Post)]
[HttpPost]
public ActionResult Create([Bind(Exclude = "EMP_ID")] EMP_MAIN_TBL employeeToCreate)
{
if (!_service.CreateEmployee(employeeToCreate))
return View();
return RedirectToAction("Index");
}
}
}
and my view looks like this
My question is above code working fine for server side validation
but how do I achieve validation on client side using above same code
please
Since you are already validating on the service side you could return the ModelStateDictionary instead of the bool, you could then check that it is valid on the client side.
But this won't help when it comes to checking that the whole service method has finished, so you could create a new type that returns say a bool and the ModelStateDictionary.
Another approach is to use Fault Exceptions. You can create your own fault exception that would get thrown when the model state is not valid. This Model State Fault could contain your ModelStateDictionary.
So from that you have three options.
Change the return type to the ModelStateDictionary.
Create a new return type to return a result and a ModelStateDictionary.
Use Fault Exceptions that occur when the Model State isn't valid.
Personally I would use the third approach, as you can then still use your original return type, and then just need to catch the Fault like you would an Exception. Here is an example and also MSDN

Categories