I have the below code which initiates the browser in each test. However the first Test runs OK correctly starting the browser. The second Test on wards start to fail
public class BrowserFactory
{
private static IWebDriver driver;
public static IWebDriver Driver
{
get
{
if (driver == null)
throw new NullReferenceException("The WebDriver browser instance was not initialized. You should first call the method InitBrowser.");
return driver;
}
set
{
driver = value;
}
}
public static void InitBrowser(string browserName)
{
switch (browserName)
{
case "Firefox":
if (driver == null)
{
driver = new FirefoxDriver();
driver.Manage().Window.Maximize();
}
break;
case "IE":
if (driver == null)
{
driver = new InternetExplorerDriver();
driver.Manage().Window.Maximize();
}
break;
case "Chrome":
if (driver == null)
{
driver = new ChromeDriver();
driver.Manage().Window.Maximize();
}
break;
}
}
And this is how I initiate and quit browser in each test
[TestFixture]
public class AdminUserHasAccessToDashboard
{
[SetUp]
public void GotoHomePage()
{
BrowserFactory.InitBrowser("Chrome");
BrowserFactory.LoadApplication(ConfigurationManager.AppSettings["URL"]);
}
[TearDown]
public void Quit()
{
BrowserFactory.CloseAllDrivers();
}
It looks like you are probably setting driver instance in your first test and other tests are false on if (driver == null), so other instances will never be created. Your code is incomplete so I can't be sure, but it seems to be an issue here.
How are you closing your driver after first test is completed?
Include the method mentioned below in your browser factory and call at the end of each test, or set up before the tests are run then use the single instance for each test and tear down at the end.
public static void Quit(){
if (Driver!= null)
Driver.Quit();
}
I use a static "Driver" class which is referenced in each test class (not each test case)
I include this in each class(they are nunit C# tests)
#region Initialise and clean up
[OneTimeSetUp]
public void Init()
{
Driver.Initialise();
}
[OneTimeTearDown]
public void CleanUp()
{
Driver.Quit();
}
#endregion
Then my driver class is as below, the appstate region wont apply but can be edited to suit your needs.
using System;
using System.Threading;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using AdaptiveAds_TestFramework.PageFrameworks;
namespace AdaptiveAds_TestFramework.Helpers
{
/// <summary>
/// Contains functionality for browser automation.
/// </summary>
public static class Driver
{
#region Variables
private static IWebDriver _instance;
private static Period _waitPeriod;
#endregion//Variables
#region Properties
/// <summary>
/// Browser automation object.
/// </summary>
public static IWebDriver Instance
{
get { return _instance; }
set { _instance = value; SetWait(WaitPeriod); }
}
/// <summary>
/// Duration automation framework must wait before throwing an error.
/// </summary>
public static Period WaitPeriod
{
get { return _waitPeriod; }
set
{
_waitPeriod = value;
SetWait(_waitPeriod);
}
}
#endregion//Properties
#region Methods
#region set-up and tear-down
/// <summary>
/// Sets up a new automation object.
/// </summary>
public static void Initialise()
{
Quit();
Instance = new FirefoxDriver(new FirefoxBinary(ConfigData.FireFoxPath), new FirefoxProfile());
Instance.Manage().Window.Maximize();
WaitPeriod = ConfigData.DefaultWaitPeriod;
}
/// <summary>
/// Disposes of the automation object.
/// </summary>
public static void Quit()
{
if (Instance != null)
Instance.Quit();
}
#endregion //set-up and tear-down
#region NavigableLocations
/// <summary>
/// Navigate browser to a given location.
/// </summary>
/// <param name="location">Location to navigate to.</param>
/// <param name="logInIfNeeded">Logs in if authentication is required.</param>
/// <param name="errorIfNotReached">Errors if the location was not reached.</param>
public static void GoTo(Location location, bool logInIfNeeded, bool errorIfNotReached)
{
// Navigate browser to the location.
Instance.Navigate().GoToUrl(Helper.RouteUrl(location));
Thread.Sleep(500);// wait for system to navigate
bool needToLogIn = false;
if (logInIfNeeded)
{
try
{
IsAt(Location.Login);
needToLogIn = true;
}
catch
{
// Not at login page so Login not needed.
}
if (needToLogIn)
{
LoginPage.LoginAs(ConfigData.Username).WithPassword(ConfigData.Password).Login();
GoTo(location, false, errorIfNotReached);
}
}
if (errorIfNotReached)
{
IsAt(location);
}
}
/// <summary>
/// Ensures the Driver is at the specified location, throws a WebDriverException if at another location.
/// </summary>
/// <param name="location">Location to check the browser is at.</param>
public static void IsAt(Location location)
{
string expected = Helper.RouteUrl(location);
string actual = Instance.Url;
// Check the browser is at the correct location.
if (actual != expected)
{
// Driver is not at the specified location.
throw new WebDriverException("Incorrect location.",
new InvalidElementStateException(
"The given location did not match the browser." +
" Expected \"" + expected + "\" Actual \"" + actual + "\""));
}
ActionWait(Period.None, CheckForLavarelError);
}
/// <summary>
/// Ensures the Driver is not at the specified location, throws a WebDriverException if at the location.
/// </summary>
/// <param name="location">Location to check the browser is not at.</param>
public static void IsNotAt(Location location)
{
string expected = Helper.RouteUrl(location);
string actual = Instance.Url;
// Check the browser is not at the correct location.
if (actual == expected)
{
// Driver is at the specified location.
throw new WebDriverException("Incorrect location.",
new InvalidElementStateException(
"The given location matched the browser."));
}
}
#endregion//NavigableLocations
#region WaitHandling
/// <summary>
/// Performs an action with a temporary wait period.
/// </summary>
/// <param name="waitPeriod">Period to wait while executing action.</param>
/// <param name="action">Action to execute.</param>
public static void ActionWait(Period waitPeriod, Action action)
{
// Store the current wait period
Period previousPeriod = WaitPeriod;
// Run task with given wait period
SetWait(waitPeriod);
action();
// Revert to the old wait period
SetWait(previousPeriod);
}
/// <summary>
/// Updates the Automation instance wait period.
/// </summary>
/// <param name="waitPeriod">New wait period.</param>
private static void SetWait(Period waitPeriod)
{
int miliseconds;
ConfigData.WaitPeriods.TryGetValue(waitPeriod, out miliseconds);
// Set the drivers instance to use the wait period.
if (Instance != null)
{
Instance.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromMilliseconds(miliseconds));
}
}
#endregion//WaitHandling
#region AppState
/// <summary>
/// Checks that the website hasn't crashed from the back end.
/// </summary>
public static void CheckForLavarelError()
{
bool error = false;
try
{
Instance.FindElement(By.ClassName("exception_message"));
error = true;
}
catch
{
// all good, could not find error content.
}
if (error)
{
throw new Exception("Lavarel threw an error");
}
}
/// <summary>
/// Clicks on the main menu button to open or close the main menu.
/// </summary>
public static void OpenCloseMenuBar()
{
try
{
IWebElement menuButton = Instance.FindElement(By.Name(ConfigData.MainMenuButtonName));
menuButton.Click();
}
catch (Exception e)
{
throw new NoSuchElementException("Could not find the Menu button element.", e);
}
}
/// <summary>
/// Asserts the logged in state agents the parameter.
/// </summary>
/// <param name="checkLoggedIn">Parameter to check agents logged in state.</param>
public static void LoggedIn(bool checkLoggedIn)
{
OpenCloseMenuBar();
bool signInFound;
bool signOutFound;
bool isLoggedIn = false;
try { Instance.FindElement(By.Name(ConfigData.SignInName)); signInFound = true; }
catch { signInFound = false; }
try { Instance.FindElement(By.Name(ConfigData.SignOutName)); signOutFound = true; }
catch { signOutFound = false; }
if (!signInFound && !signOutFound)
{
throw new ElementNotVisibleException("Unable to assert state due to unavailability of SignIn/Out links.");
}
if (signOutFound) isLoggedIn = true;
if (signInFound) isLoggedIn = false;
if (isLoggedIn != checkLoggedIn)
{
throw new Exception($"Logged in Expected: {checkLoggedIn} Actual: {isLoggedIn}");
}
}
/// <summary>
/// Signs out of the system.
/// </summary>
/// <param name="errorIfAlreadySignedOut">Determines whether to throw an error if already signed out.</param>
public static void SignOut(bool errorIfAlreadySignedOut = true)
{
try
{
LoggedIn(true);
}
catch (Exception)
{
if (errorIfAlreadySignedOut)
{
throw;
}
return;
}
IWebElement signOut = Instance.FindElement(By.Name(ConfigData.SignOutName));
signOut.Click();
Thread.Sleep(500);// wait for system to logout
}
#endregion//AppState
#endregion//Methods
}
}
Related
I am creating a custom control in Xamarin.Forms which is inherited from TemplatedView and using the application in all three platforms. For testing purposes, I need to set Automation ID for all native controls.
Usually, by using AutomationPeer we can set Automation ID to native UWP control from the UWP renderer project. But, in my custom control, I get this. Control is null always.
So, I can’t set Automation ID in UWP renderer class as Forms TemplatedView is a FrameworkElement in UWP.
My query is,
How to get a native element (this.Control) in UWP renderer project for Xamarin.Forms TemplatedView.
How to set Automation Id to native UWP control if this.Control is null.
The code snippet is provided below:
class FormsCustomLayout : TemplatedView
{
public static readonly BindableProperty InputViewProperty =
BindableProperty.Create(nameof(InputView), typeof(View), typeof(FormsCustomLayout), null, BindingMode.Default, null, OnInputViewChanged);
private static void OnInputViewChanged(BindableObject bindable, object oldValue, object newValue)
{
(bindable as FormsCustomLayout).OnInputViewChanged(oldValue, newValue);
}
private void OnInputViewChanged(object oldValue, object newValue)
{
var oldView = (View)oldValue;
if (oldView != null)
{
if (this.contentGrid.Children.Contains(oldView))
{
oldView.SizeChanged -= OnInputViewSizeChanged;
oldView.BindingContext = null;
this.contentGrid.Children.Remove(oldView);
}
}
var newView = (View)newValue;
if (newView != null)
{
newView.SizeChanged += OnInputViewSizeChanged;
newView.VerticalOptions = LayoutOptions.CenterAndExpand;
newView.HeightRequest = 60;
this.contentGrid.Children.Add(newView);
}
}
private void OnInputViewSizeChanged(object sender, EventArgs e)
{
}
public View InputView
{
get { return (View)GetValue(InputViewProperty); }
set { SetValue(InputViewProperty, value); }
}
internal void UpdateText(object text)
{
this.Text = (string)text;
}
private readonly Grid contentGrid = new Grid();
public FormsCustomLayout()
{
this.ControlTemplate = new ControlTemplate(typeof(StackLayout));
((StackLayout)Children[0]).Children.Add(this.contentGrid);
if (InputView != null)
{
this.contentGrid.Children.Add(InputView);
}
}
internal string Text { get; private set; }
}
The custom renderer code snippet is provided below:
class FormsCustomLayoutRenderer : ViewRenderer<FormsCustomLayout, FrameworkElement>
{
/// <summary>
/// Method that is called when the automation id is set.
/// </summary>
/// <param name="id">The automation id.</param>
protected override void SetAutomationId(string id)
{
if (this.Control == null)
{
base.SetAutomationId(id);
}
else
{
this.SetAutomationPropertiesAutomationId(id);
this.Control.SetAutomationPropertiesAutomationId(id);
}
}
/// <summary>
/// Provide automation peer for the control
/// </summary>
/// <returns>The TextInputLayout view automation peer.</returns>
protected override AutomationPeer OnCreateAutomationPeer()
{
if (this.Control == null)
{
return new FormsCustomLayoutAutomationPeer(this);
}
return new FormsCustomLayoutAutomationPeer(this.Control);
}
protected override void OnElementChanged(ElementChangedEventArgs<FormsCustomLayout> e)
{
base.OnElementChanged(e);
var element = e.NewElement;
}
}
internal class FormsCustomLayoutAutomationPeer : FrameworkElementAutomationPeer
{
/// <summary>
/// Initializes a new instance of the <see cref="FormsCustomLayoutRenderer"/> class.
/// </summary>
/// <param name="owner">FormsCustomLayout View control</param>
public FormsCustomLayoutAutomationPeer(FrameworkElement owner) : base(owner)
{
}
/// <summary>
/// Describe the control type
/// </summary>
/// <returns>The control type.</returns>
protected override AutomationControlType GetAutomationControlTypeCore()
{
return AutomationControlType.Custom;
}
/// <summary>
/// Describe the class name.
/// </summary>
/// <returns>The Class Name.</returns>
protected override string GetClassNameCore()
{
return "FormsCustomLayout";
}
}
Demo sample attached here: FormsCustomControl
Please share your idea or solution to set Automation ID.
Regards,
Bharathiraja.
I´m developing an ASP.NET MVC Application, in which I use NHibernate and Ninject.
The Problem is caused by the following Controller:
public class ShoppingCartController : Controller
{
private readonly Data.Infrastructure.IShoppingCartRepository _shoppingCartRepository;
private readonly Data.Infrastructure.IShopItemRepository _shopItemRepository;
public ShoppingCartController(Data.Infrastructure.IShoppingCartRepository shoppingCartController,
Data.Infrastructure.IShopItemRepository shopItemRepository)
{
_shoppingCartRepository = shoppingCartController;
_shopItemRepository = shopItemRepository;
}
public ActionResult AddToShoppingCart(FormCollection formCollection)
{
var cartItem = new Data.Models.ShoppingCartItem();
cartItem.ChangeDate = DateTime.Now;
cartItem.ShopItem = _shopItemRepository.GetShopItem(SessionData.Data.Info, Convert.ToInt32(formCollection["shopItemId"]));
//IF I DONT´T CALL THE METHOD ABOVE, AddToCart works
_shoppingCartRepository.AddToCart(SessionData.Data.Info, cartItem);
//BUT IF I CALL THE GetShopItem METHOD I GET THE EXCEPTION HERE!
return RedirectToAction("Index", "Shop");
}
}
I know most of the Time this Exception is caused by wrong Mapping, but I´m pretty sure that my Mapping is right because the AddToCart-Method works if I don´t call GetShopItem...
So here is the Code of the ShopItemRepository:
public class ShopItemRepository : ReadOnlyRepository<ShopItem>, IShopItemRepository
{
public ShopItemRepository(IUnitOfWork uow) : base(uow)
{
}
public ShopItem GetShopItem(SessionParams param, int id)
{
return CurrentSession.QueryOver<ShopItem>()
.Where(x => x.ProcessId == param.ProcessId &&
x.CatalogueId == param.CatalogueId &&
x.Id == id)
.SingleOrDefault();
}
public IList<ShopItem> GetShopItems(SessionParams param)
{
return CurrentSession.GetNamedQuery("GetShopItems")
.SetParameter("requestor_id", param.RequestorId)
.SetParameter("recipient_id", param.RecipientId)
.SetParameter("process_id", param.ProcessId)
.SetParameter("catalogue_id", param.CatalogueId)
.List<ShopItem>();
}
}
And finally the Code of my UnitOfWork (basically it is just a Wrapper for the Session because I don´t want to reference NHibernate in my MVC Project)
public class UnitOfWork : IUnitOfWork, IDisposable
{
private NHibernate.ISession _currentSession;
public NHibernate.ISession CurrentSession
{
get
{
if(_currentSession == null)
{
_currentSession = SessionFactoryWrapper.SessionFactory.OpenSession();
}
return _currentSession;
}
}
public void Dispose()
{
if(_currentSession != null)
{
_currentSession.Close();
_currentSession.Dispose();
_currentSession = null;
}
GC.SuppressFinalize(this);
}
}
Addendum:
My NinjectWebCommon Class
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
kernel.Bind<Data.Infrastructure.ICatalogueRepository>().To<Data.Repositories.CatalogueRepository>();
kernel.Bind<Data.Infrastructure.ICategoryRepository>().To<Data.Repositories.CategoryRepository>();
kernel.Bind<Data.Infrastructure.IContactRepository>().To<Data.Repositories.ContactRepository>();
kernel.Bind<Data.Infrastructure.IProcessRepository>().To<Data.Repositories.ProcessRepository>();
kernel.Bind<Data.Infrastructure.IShopItemRepository>().To<Data.Repositories.ShopItemRepository>();
kernel.Bind<Data.Infrastructure.IShoppingCartRepository>().To<Data.Repositories.ShoppingCartRepository>();
}
}
IUnitOfWork is set to RequestScope so in the Case of ShoppingCartController, the two Repositories share the same UOW right?
Maybe this could cause the Problem?
Are you sure that this isn´t caused by wrong mapping? I had the same Issue and could resolve it by checking my mappings again!
In my application i discovered that sometimes the Close() for a WCF-call/channels trowed errors.
And i did a little research on the subject and borrowed some code on the internet to get me started.
And now, I wonder is this the right way to go? or should i improve the solution or maybe implement something totally different?
Generic-Class/Static Class:
public class SafeProxy<Service> : IDisposable where Service : ICommunicationObject
{
private readonly Service _proxy;
public SafeProxy(Service s)
{
_proxy = s;
}
public Service Proxy
{
get { return _proxy; }
}
public void Dispose()
{
if (_proxy != null)
_proxy.SafeClose();
}
}
public static class Safeclose
{
public static void SafeClose(this ICommunicationObject proxy)
{
try
{
proxy.Close();
}
catch
{
proxy.Abort();
}
}
}
This is how i make calls to the WCF:
(The WCFReference is a Service Reference pointing to the WCF service adress)
using (var Client = new SafeProxy<WCFReference.ServiceClient>(new WCFReference.ServiceClient()))
{
Client.Proxy.Operation(info);
}
Here's a quick little extension method I use to safely interact with a WCF service from the client:
/// <summary>
/// Helper class for WCF clients.
/// </summary>
internal static class WcfClientUtils
{
/// <summary>
/// Executes a method on the specified WCF client.
/// </summary>
/// <typeparam name="T">The type of the WCF client.</typeparam>
/// <typeparam name="TU">The return type of the method.</typeparam>
/// <param name="client">The WCF client.</param>
/// <param name="action">The method to execute.</param>
/// <returns>A value from the executed method.</returns>
/// <exception cref="CommunicationException">A WCF communication exception occurred.</exception>
/// <exception cref="TimeoutException">A WCF timeout exception occurred.</exception>
/// <exception cref="Exception">Another exception type occurred.</exception>
public static TU Execute<T, TU>(this T client, Func<T, TU> action) where T : class, ICommunicationObject
{
if ((client == null) || (action == null))
{
return default(TU);
}
try
{
return action(client);
}
catch (CommunicationException)
{
client.Abort();
throw;
}
catch (TimeoutException)
{
client.Abort();
throw;
}
catch
{
if (client.State == CommunicationState.Faulted)
{
client.Abort();
}
throw;
}
finally
{
try
{
if (client.State != CommunicationState.Faulted)
{
client.Close();
}
}
catch
{
client.Abort();
}
}
}
}
I call it as such:
var result = new WCFReference.ServiceClient().Execute(client => client.Operation(info));
I am running into the below error the first time my ViewModel is being instantiated by the SimpleIoC. I believe I have setup the container as it should be, but for some reason, I am still getting the below error. Any ideas or assistance would be very much appreciated.
Microsoft.Practices.ServiceLocation.ActivationException was unhandled by user code
HResult=-2146233088
Message=Type not found in cache: Windows.UI.Xaml.Controls.Frame.
Source=GalaSoft.MvvmLight.Extras
StackTrace:
at GalaSoft.MvvmLight.Ioc.SimpleIoc.DoGetService(Type serviceType, String key) in c:\Users\Public\Downloads\CodePlex\MVVMLight\GalaSoft.MvvmLight\GalaSoft.MvvmLight.Extras (NET35)\Ioc\SimpleIoc.cs:line 532
at GalaSoft.MvvmLight.Ioc.SimpleIoc.GetService(Type serviceType) in c:\Users\Public\Downloads\CodePlex\MVVMLight\GalaSoft.MvvmLight\GalaSoft.MvvmLight.Extras (NET35)\Ioc\SimpleIoc.cs:line 768
at GalaSoft.MvvmLight.Ioc.SimpleIoc.MakeInstance[TClass]() in c:\Users\Public\Downloads\CodePlex\MVVMLight\GalaSoft.MvvmLight\GalaSoft.MvvmLight.Extras (NET35)\Ioc\SimpleIoc.cs:line 708
InnerException:
Here are pieces of my code related to this:
ViewModelLocator.cs (Located in my Win8 project)
public class ViewModelLocator
{
/// <summary>
/// Initializes a new instance of the ViewModelLocator class.
/// </summary>
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
{
// Create design time view services and models
//SimpleIoc.Default.Register<IDataService, DesignDataService>();
}
else
{
// Create run time view services and models
//SimpleIoc.Default.Register<IDataService, DataService>();
SimpleIoc.Default.Register<INavigationService, NavigationService>();
SimpleIoc.Default.Register<IParseService, ParseService>();
SimpleIoc.Default.Register<IServiceHandler, ServiceHandler>();
}
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<ActionViewModel>();
}
public MainViewModel MainVM
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
public ActionViewModel ActionVM
{
get
{
return ServiceLocator.Current.GetInstance<ActionViewModel>();
}
}
public static void Cleanup()
{
// TODO Clear the ViewModels
}
}
MainViewModel.cs Constructor
public class MainViewModel : ViewModelBase
{
#region Variables
private readonly INavigationService _navigationService;
private readonly IParseService _parseService;
#endregion
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel(INavigationService navigationService, IParseService parseService)
{
if (IsInDesignMode)
{
// Code runs in Blend --> create design time data.
}
else
{
_navigationService = navigationService;
_parseService = parseService;
BuildCommonData();
}
}
I know this is long overdue, but here is the offending code in the implementation of my NavigationService class.
NavigationService class (Before)
public class NavigationService : INavigationService
{
/// <summary>
/// Gets the root frame.
/// </summary>
private Frame RootFrame;
public NavigationService(Frame rootFrame)
{
RootFrame = rootFrame;
}
public event NavigatingCancelEventHandler Navigating;
public void Navigate<T>(object parameter = null)
{
var type = typeof(T);
RootFrame.Navigate(type, parameter);
}
public void Navigate(string type, object parameter = null)
{
RootFrame.Navigate(Type.GetType(type), parameter);
}
public void GoBack()
{
if (RootFrame.CanGoBack)
{
RootFrame.GoBack();
}
}
public void GoForward()
{
if (RootFrame.CanGoForward)
{
RootFrame.GoForward();
}
}
}
I simply took out the constructor, and made the RootFrame private variable a property. Like so:
public class NavigationService : INavigationService
{
/// <summary>
/// Gets the root frame.
/// </summary>
private static Frame RootFrame
{
get { return Window.Current.Content as Frame; }
}
public event NavigatingCancelEventHandler Navigating;
public void Navigate<T>(object parameter = null)
{
var type = typeof(T);
RootFrame.Navigate(type, parameter);
}
public void Navigate(string type, object parameter = null)
{
RootFrame.Navigate(Type.GetType(type), parameter);
}
public void GoBack()
{
if (RootFrame.CanGoBack)
{
RootFrame.GoBack();
}
}
public void GoForward()
{
if (RootFrame.CanGoForward)
{
RootFrame.GoForward();
}
}
}
Simple, I know, but hope it's of some use.
I was getting the same error today in my Xamarin project. The actual error given was "System.Reflection.TargetInvocationException: 'Exception has been thrown by the target of an invocation.'" and then when I look up the InnerException I could see the actual error, which is Type not found in cache.
It was a silly mistake that I was using DataService instead of IDataService for the Constructor Dependency Injection.
public SearchViewModel(DataService dataService, IErrorLoggingService errorLoggingService, IDialogService dialogService, IResourceService resourceService, INavigationService navigationService) {
SearchCommand = new AsyncRelayCommand <SearchFilter>(SearchAsync);
DataService = dataService;
ErrorLoggingService = errorLoggingService;
DialogService = dialogService;
ResourceService = resourceService;
NavigationService = navigationService;
CancelCommand = new RelayCommand(Cancel);
}
And just for your information, this is how I registered my service.
SimpleIoc.Default.Register<IDataService, DataService>();
So the issue was fixed after changing to IDataService. Hope it helps.
I'm subclassing the AuthorizeAttribute so I can implement token authentication whereby the token is passed in the request header. I'm also using Ninject for IoC. The overriden OnAuthorization method gets called and validates the token but I still receive a 401.
Any ideas on why this is happening?
TokenAuthorisationAttribute.cs
public class TokenAuthorisationAttribute : AuthorizeAttribute
{
private readonly IRepository _repository;
public TokenAuthorisationAttribute(IRepository repository)
{
_repository = repository;
}
public override void OnAuthorization(
HttpActionContext actionContext)
{
if (!ValidateToken(actionContext.ControllerContext.Request))
HandleUnauthorizedRequest(actionContext);
base.OnAuthorization(actionContext);
}
private bool ValidateToken(HttpRequestMessage request)
{
const string authenticationToken = "Authentication-Token";
var token = request.Headers.GetValues(authenticationToken).FirstOrDefault();
if (token == null)
return false;
var device = _repository.FindSingleOrDefault<Device>(x => x.Id.Equals(token));
if (device == null || !token.Equals(device.Id))
return false;
return true;
}
}
NinjectWebCommon.cs
public static class NinjectWebCommon
{
private static readonly Bootstrapper Bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
Bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
Bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
var connectionString = ConfigurationManager.ConnectionStrings["MONGOHQ_URL"].ConnectionString;
var databaseName = ConfigurationManager.AppSettings["Database"];
kernel.Bind<IRepository>().To<MongoRepository>()
.WithConstructorArgument("connectionString", connectionString)
.WithConstructorArgument("databaseName", databaseName);
kernel.BindHttpFilter<TokenAuthorisationAttribute>(FilterScope.Global);
}
I managed to resolve this issue by overriding the IsAuthorized method instead of OnAuthorization. Not 100% sure if this is the right approach? Any opinions ??
public class TokenAuthorisationAttribute : AuthorizeAttribute
{
private readonly IRepository _repository;
public TokenAuthorisationAttribute(IRepository repository)
{
_repository = repository;
}
protected override bool IsAuthorized(HttpActionContext actionContext)
{
if (actionContext.Request.Headers.Authorization == null)
return false;
var authToken = actionContext.Request.Headers.Authorization.Parameter;
var decodedToken = Encoding.UTF8.GetString(Convert.FromBase64String(authToken));
var deviceToken = new DeviceToken(decodedToken);
var device = _repository.FindSingleOrDefault<Device>(x => x.Id.Equals(deviceToken.GetDeviceId()));
if (device != null)
{
HttpContext.Current.User = new GenericPrincipal(new ApiIdentity(device), new string[] {});
return true;
}
return base.IsAuthorized(actionContext);
}
}
The ASP.NET WebAPI is an open source project. So you can read the correspondingly codes here:
AuthorizationFilterAttribute http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/03357424caf5#src%2fSystem.Web.Http%2fFilters%2fAuthorizationFilterAttribute.cs
AuthorizeAttribute
http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/03357424caf5#src%2fSystem.Web.Http%2fAuthorizeAttribute.cs
There are two facts an AuthorizationFilterAttribute takes in to consider when it is making decision:
Is OnAuthorization throw exception; or
Is the actionContext's Response field is filled;
Either one is fulfilled, the remaining action filters and action are shortcut.
Based on your code, I'm curious if the function HandleUnauthorizedRequest does either of the operation above.
The reason why overriding IsAuthorized works, is because it works at AuthorizeAttribute level. The OnAuthorization call to the IsAuthorized overload and set value to actionContext's Request property.
Thanks,
Troy