I'm following mvvmcross tutorial for iOS project. I think I'm doing exactly for is described there, but when I run the appliaction I'm getting following error:
ObjCRuntime.RuntimeException
Message=Failed to lookup the required marshalling information.
Additional information:
Selector: setGenerositySlider:
Type: TipView
Source=
StackTrace:
at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain(int,string[],intptr,intptr)
at UIKit.UIApplication.Main (System.String[] args, System.IntPtr principal, System.IntPtr delegate) [0x00005] in /Library/Frameworks/Xamarin.iOS.framework/Versions/14.2.0.12/src/Xamarin.iOS/UIKit/UIApplication.cs:86
at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0000e] in /Library/Frameworks/Xamarin.iOS.framework/Versions/14.2.0.12/src/Xamarin.iOS/UIKit/UIApplication.cs:65
at TipCalc.iOS.Application.Main (System.String[] args) [0x00001] in C:\Users\MYUSERNAME\source\repos\xamarin\TipCalc.Core\TipCalc.iOS\Main.cs:12
I cloned the same project from the samples and it runs fine. I think I compared everything I could and projects are the same as far as I can tell.
namespace TipCalc.iOS
{
public class Application
{
// This is the main entry point of the application.
static void Main(string[] args)
{
// if you want to use a different Application Delegate class from "AppDelegate"
// you can specify it here.
UIApplication.Main(args, null, "AppDelegate");
}
}
}
namespace TipCalc.iOS
{
[Register(nameof(AppDelegate))]
public class AppDelegate : MvxApplicationDelegate<MvxIosSetup<App>, App>
{
public override UIWindow Window { get; set; }
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
var result = base.FinishedLaunching(application, launchOptions);
return result;
}
}
}
public partial class TipView : MvxViewController<TipViewModel>
{
public TipView() : base(nameof(TipView), null)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
var set = this.CreateBindingSet<TipView, TipViewModel>();
set.Bind(TipLabel).To(vm => vm.Tip);
set.Bind(SubTotalTextField).To(vm => vm.SubTotal);
set.Bind(GenerositySlider).To(vm => vm.Generosity);
set.Apply();
View.AddGestureRecognizer(new UITapGestureRecognizer(() =>
{
this.SubTotalTextField.ResignFirstResponder();
}));
}
}
Generated code behind
namespace TipCalc.iOS
{
[Register ("TipView")]
partial class TipView
{
[Outlet]
[GeneratedCode ("iOS Designer", "1.0")]
UISlider GenerositySlider { get; set; }
[Outlet]
[GeneratedCode ("iOS Designer", "1.0")]
UITextField SubTotalTextField { get; set; }
[Outlet]
[GeneratedCode ("iOS Designer", "1.0")]
UILabel TipLabel { get; set; }
void ReleaseDesignerOutlets ()
{
if (GenerositySlider != null) {
GenerositySlider.Dispose ();
GenerositySlider = null;
}
if (SubTotalTextField != null) {
SubTotalTextField.Dispose ();
SubTotalTextField = null;
}
if (TipLabel != null) {
TipLabel.Dispose ();
TipLabel = null;
}
}
}
}
What am I missing here?
I didn't set File's Owners class, adding it resolved the problem.
Related
I use Xamarin.Forms, but I do the necessary actions on the iOS side, but Facebook does not verify the update.
and I'm new to this problem I had no such problems in advance.
I using plugin: Xamarin.Facebook.iOS (4.39.1)
SDK is up to date, although I have done all the necessary applications, my problem is not solved.
using System;
using System.Linq;
using Firebase.Analytics;
using Foundation;
using Google.TagManager;
using Plugin.FirebasePushNotification;
using UIKit;
namespace XXX.iOS
{
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
public bool disableAllOrientation = true;
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
Facebook.CoreKit.Settings.AppID = "xxx";
Facebook.CoreKit.Settings.DisplayName = "xxxxx";
Rg.Plugins.Popup.Popup.Init();
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
TagManager.Configure();
Firebase.Core.App.Configure();
GoogleConversionTracking.Unified.ACTConversionReporter.ReportWithConversionId("xxxx", "xxxx", "0.00", false);
Facebook.CoreKit.ApplicationDelegate.SharedInstance.FinishedLaunching(app, options);
FirebasePushNotificationManager.Initialize(options, true);
CrossFirebasePushNotification.Current.RegisterForPushNotifications();
return base.FinishedLaunching(app, options);
}
public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, UIWindow forWindow)
{
if (disableAllOrientation == true)
{
return UIInterfaceOrientationMask.Portrait;
}
return UIInterfaceOrientationMask.All;
}
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
FirebasePushNotificationManager.DidRegisterRemoteNotifications(deviceToken);
}
public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
{
FirebasePushNotificationManager.RemoteNotificationRegistrationFailed(error);
}
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
FirebasePushNotificationManager.DidReceiveMessage(userInfo);
System.Console.WriteLine(userInfo);
}
public override void OnActivated(UIApplication uiApplication)
{
FirebasePushNotificationManager.Connect();
// FacebookClientManager.OnActivated();
Facebook.CoreKit.AppEvents.ActivateApp();
}
public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
{
return Facebook.CoreKit.ApplicationDelegate.SharedInstance.OpenUrl(app, url, options);
// return FacebookClientManager.OpenUrl(app, url, options);
}
public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
{
Analytics.HandleOpenUrl(url);
return
Facebook.CoreKit.ApplicationDelegate.SharedInstance.OpenUrl(application, url, sourceApplication,annotation);
///eturn FacebookClientManager.OpenUrl(application, url, sourceApplication, annotation);
}
public override void DidEnterBackground(UIApplication application)
{
// Use this method to release shared resources, save user data, invalidate timers and store the application state.
// If your application supports background exection this method is called instead of WillTerminate when the user quits.
var lastObject = UIApplication.SharedApplication.KeyWindow.Subviews.Last();
if (lastObject != null)
{
UIVisualEffect blurEffect = UIBlurEffect.FromStyle(UIBlurEffectStyle.Dark);
UIVisualEffectView visualEffectView = new UIVisualEffectView(blurEffect)
{
Frame = UIScreen.MainScreen.Bounds
};
lastObject.AddSubview(visualEffectView);
}
base.DidEnterBackground(application);
FirebasePushNotificationManager.Disconnect();
}
public override void WillEnterForeground(UIApplication uiApplication)
{
var lastObject = UIApplication.SharedApplication.KeyWindow.Subviews.Last();
if (lastObject != null)
{
var lastSub = lastObject.Subviews.Last();
lastSub.RemoveFromSuperview();
}
base.WillEnterForeground(uiApplication);
}
public override void WillTerminate(UIApplication uiApplication)
{
UIPasteboard.General.Items = new NSDictionary[0];
base.WillTerminate(uiApplication);
}
}
}
i am trying to set MainPage whenever logout button taps but i am getting below mentioned exception.
Logout Function:
private void Logout()
{
//Settings.Current.Remove(Constants.PREF_IS_LOGGED_IN);
//Settings.Current.Remove(Constants.PREF_AUTH_TOKEN);
MainPage = new NavigationPage(new LoginPage());
}
LoginPageViewModel:
using Prism.Mvvm;
using Prism.Navigation;
using SalesApp.Controllers.RestController;
using System;
using System.Windows.Input;
using Xamarin.Forms;
using Acr.Settings;
using Plugin.Connectivity;
using SalesApp.Utils;
using SalesApp.Views;
using SalesApp.Views.SideMenu;
using Acr.UserDialogs;
using SalesApp.Interfaces;
namespace SalesApp.ViewModels
{
public class LoginPageViewModel : BindableBase, INavigationAware
{
private String _email = Constants.Username; // dummy value
private String _password = Constants.Password; // dummy value
private Boolean _isShowPassword = true;
private Boolean _isShowPasswordIcon = false;
private Boolean _isRememberMe = false;
ICommand _tapCommandShowPassword;
ICommand _tapCommandNavigateForgotPassword;
ICommand _login;
INavigationService _navigationService;
public DataManager DataManager { get; private set; }
public LoginPageViewModel(INavigationService navigationService)
{
_tapCommandShowPassword = new Command(ShowHidePassword);
_tapCommandNavigateForgotPassword = new Command(NavigateToForgotPassword);
_login = new Command(LoginApiCalls);
_navigationService = navigationService;
}
public String Email
{
get
{
return _email;
}
set
{
_email = value;
}
}
public String Password
{
get
{
return _password;
}
set
{
_password = value;
if (_password.Length > 0)
IsShowPasswordIcon = true;
else
{
IsShowPasswordIcon = false;
IsShowPassword = true;
}
}
}
public bool IsShowPassword
{
get
{
return _isShowPassword;
}
set
{
_isShowPassword = value;
RaisePropertyChanged("IsShowPassword");
}
}
public bool IsRememberMe
{
get
{
return _isRememberMe;
}
set
{
_isRememberMe = value;
RaisePropertyChanged("IsRememberMe");
}
}
public bool IsShowPasswordIcon
{
get
{
return _isShowPasswordIcon;
}
set
{
_isShowPasswordIcon = value;
RaisePropertyChanged("IsShowPasswordIcon");
}
}
public ICommand TapCommandShowPassword
{
get { return _tapCommandShowPassword; }
}
public ICommand TapCommandNavigateForgotPassword
{
get { return _tapCommandNavigateForgotPassword; }
}
public ICommand Login
{
get { return _login; }
}
public void OnNavigatedFrom(NavigationParameters parameters)
{
}
public void OnNavigatedTo(NavigationParameters parameters)
{
}
public void OnNavigatingTo(NavigationParameters parameters)
{
}
void ShowHidePassword()
{
IsShowPassword = !IsShowPassword;
if (IsShowPassword)
IsShowPassword = true;
else
IsShowPassword = false;
}
void NavigateToForgotPassword()
{
_navigationService.NavigateAsync("ForgotPasswordPage");
}
async void LoginApiCalls(object s)
{
if (CrossConnectivity.Current.IsConnected)
{
try
{
UserDialogs.Instance.ShowLoading(ResX.AppResources.Loading_mesg, MaskType.Black);
if (_tapCommandNavigateForgotPassword != null)
{
DataManager = new DataManager(new RestService());
var resp = await DataManager.GetAuthToken(_password);
var isSuccess = false;
if (resp != null)
isSuccess = resp.IsSuccess;
if (isSuccess)
resp = await DataManager.GetUerAuth(_email, resp.Data);
if (resp.IsSuccess)
{
//store flag in shared pref
if (IsRememberMe)
{
Settings.Current.Set(Constants.PREF_IS_LOGGED_IN, true);
}
Settings.Current.Set(Constants.PREF_SALES_AGENT_ID, resp.SalesAgentId);
UserDialogs.Instance.HideLoading();
App.Current.MainPage = new NavigationPage(new HomePage());
//_navigationService.NavigateAsync("/HomePage");
}
else
{
await App.Current.MainPage.DisplayAlert(ResX.AppResources.Error_txt,
ResX.AppResources.UserName_Password_Error,ResX.AppResources.OK_txt);
UserDialogs.Instance.HideLoading();
}
}
}
catch (Exception e)
{
await App.Current.MainPage.DisplayAlert(ResX.AppResources.Error_txt,
ResX.AppResources.Generic_Error_txt, ResX.AppResources.OK_txt);
UserDialogs.Instance.HideLoading();
}
}
else
{
await App.Current.MainPage.DisplayAlert(ResX.AppResources.Net_Error_txt,
ResX.AppResources.No_Network_Error_txt, ResX.AppResources.OK_txt);
}
}
public void OnPhoneTapped(String phone)
{
var dialer = DependencyService.Get<IDialer>();
if (dialer != null)
{
dialer.Dial(phone);
}
}
public void OnRouteTap(string sourceLat, string sourceLon, string destinationLat, string destinationLon)
{
var route = DependencyService.Get<IDirection>();
if (route != null)
{
route.DrawDirection(sourceLat, sourceLon, destinationLat, destinationLon);
}
}
}
}
UNHANDLED EXCEPTION:
08-29 15:59:43.868 I/MonoDroid( 3268): System.NullReferenceException: Object reference not set to an instance of an object.
08-29 15:59:43.868 I/MonoDroid( 3268): at Xamarin.Forms.Platform.Android.AppCompat.NavigationPageRenderer.OnLayout (System.Boolean changed, System.Int32 l, System.Int32 t, System.Int32 r, System.Int32 b) [0x00007] in C:\BuildAgent3\work\ca3766cfc22354a1\Xamarin.Forms.Platform.Android\AppCompat\NavigationPageRenderer.cs:292
08-29 15:59:43.868 I/MonoDroid( 3268): at Xamarin.Forms.Platform.Android.FormsViewGroup.n_OnLayout_ZIIII (System.IntPtr jnienv, System.IntPtr native__this, System.Boolean p0, System.Int32 p1, System.Int32 p2, System.Int32 p3, System.Int32 p4) [0x00008] in C:\BuildAgent3\work\ca3766cfc22354a1\Xamarin.Forms.Platform.Android.FormsViewGroup\obj\Release\generated\src\Xamarin.Forms.Platform.Android.FormsViewGroup.cs:198
08-29 15:59:43.868 I/MonoDroid( 3268): at (wrapper dynamic-method) System.Object:bbd5dc5a-77cf-45bd-9d16-717bbe7e4232 (intptr,intptr,bool,int,int,int,int)
I am building an application using Xamarin.iOS. At first I want to display a list of categories in a GridView. For this I have used CollectionView with Custom Cell Layout. To build the Custom Cell Layout I have used "CollectioViewCell" from the interface which allows me to design the layout with Drag and Drop.
Below is the code:
ViewController.cs
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
//initialize the data
sectionCategories = new List<SectionCategory>();
sectionCategories.Add(new SectionCategory("Lajme", "LajmeUrl"));
sectionCategories.Add(new SectionCategory("Lajme", "LajmeUrl"));
sectionCategories.Add(new SectionCategory("Lajme", "LajmeUrl"));
sectionCategories.Add(new SectionCategory("Lajme", "LajmeUrl"));
sectionCategories.Add(new SectionCategory("Lajme", "LajmeUrl"));
sectionCategories.Add(new SectionCategory("Lajme", "LajmeUrl"));
sectionCategories.Add(new SectionCategory("Lajme", "LajmeUrl"));
sectionCategories.Add(new SectionCategory("Lajme", "LajmeUrl"));
sectionGrid.RegisterClassForCell(typeof(SectionViewCell), SectionViewCell.Key);
sectionGrid.Source = new SectionViewSource (sectionCategories);
}
SectionViewCell.cs
public partial class SectionViewCell : UICollectionViewCell
{
public static readonly NSString Key = new NSString ("SectionViewCell");
public static readonly UINib Nib;
static SectionViewCell ()
{
Nib = UINib.FromName ("SectionViewCell", NSBundle.MainBundle);
}
public SectionViewCell (IntPtr handle) : base (handle)
{
}
public void UpdateCell (string text)
{
imageUrl.Text = text;
sectionName.Text = text;
}
}
SectionViewCell.designer.cs
[Register ("SectionViewCell")]
partial class SectionViewCell
{
[Outlet]
[GeneratedCode ("iOS Designer", "1.0")]
UILabel imageUrl { get; set; }
[Outlet]
[GeneratedCode ("iOS Designer", "1.0")]
UILabel sectionName { get; set; }
void ReleaseDesignerOutlets ()
{
if (imageUrl != null) {
imageUrl.Dispose ();
imageUrl = null;
}
if (sectionName != null) {
sectionName.Dispose ();
sectionName = null;
}
}
}
SectionViewSource.cs
public class SectionViewSource: UICollectionViewSource
{
public List<SectionCategory> category { get; set; }
public SectionViewSource(List<SectionCategory> _category)
{
category = _category;
}
public override nint NumberOfSections (UICollectionView collectionView)
{
return 1;
}
public override nint GetItemsCount (UICollectionView collectionView, nint section)
{
return category.Count;
}
public override UICollectionViewCell GetCell (UICollectionView collectionView, NSIndexPath indexPath)
{
var cell = (SectionViewCell)collectionView.DequeueReusableCell (SectionViewCell.Key, indexPath);
cell.UpdateCell ("lajme");
return cell;
}
}
But when I run the app it throws me an error:
System.NullReferenceException: Object reference not set to an instance of an object
at MyIkub.SectionViewCell.UpdateCell (System.String text) [0x00008] in /Users/crs/Projects/MyIkub/MyIkub/SectionViewCell.cs:26
at MyIkub.SectionViewSource.GetCell (UIKit.UICollectionView collectionView, Foundation.NSIndexPath indexPath) [0x00019] in /Users/crs/Projects/MyIkub/MyIkub/SectionViewSource.cs:33
at at (wrapper managed-to-native) UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
at UIKit.UIApplication.Main (System.String[] args, IntPtr principal, IntPtr delegate) [0x00005] in /Users/builder/data/lanes/2761/d7cac503/source/maccore/src/UIKit/UIApplication.cs:77
at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0001c] in /Users/builder/data/lanes/2761/d7cac503/source/maccore/src/UIKit/UIApplication.cs:60
at MyIkub.Application.Main (System.String[] args) [0x00008] in /Users/crs/Projects/MyIkub/MyIkub/Main.cs:12
Any suggestions?
Use RegisterNibForCell instead of RegisterClassForCell.
sectionGrid.RegisterNibForCell (UINib.FromName("SectionViewCell", NSBundle.MainBundle), SectionViewCell.Key);
Here is a tutorial
I tend to dislike posting dozens of lines of code and assuming the community at large is interested in untangling my mess. In this case I've exercised everything I can think to search on Google, traced through Glimpse, and Firebug/Fiddler, and what I'm left with is an occasionally working behavior, which is particularly annoying to debug. So, I'm calling out for help.
Here's the gist: I've got a series of classes that handle MVC routes that are otherwise not found (and would produce a 404 error) thanks to #AndrewDavey. I'm attempting to intercept the 404 and show data-driven content where any exists. It all works until I refresh the page. The request works on the first load, but it never fires again after that.
If you're bored or have an itch, the entire code block is below.
Setup goes like this:
Add WebActivator via NuGet
In your AppStart folder add a cs file with the code below
Add a "PageContext" connection string to your web.config
Run the app, the default MVC screen shows up
Now add "/abc" to the end of the url (i.e http://localhost/abc)
A cshtml view, stored in the database, will render.
Change the view's markup in the database and reload the page. Notice no change in your browser.
the /abc route assumes you have a record in the database with the following
Path: "~/abc/index.cshtml"
View: "#{ Layout = null;}<!doctype html><html><head><title>abc</title></head><body><h2>About</h2></body></html>"
I've got no idea why the first request works and subsequent requests don't hit break points and serve up stale content.
My suspicions are:
Some voodoo with the VirtualFile
Something cached (but where?)
A misconfigured handler
Thanks for the help - here's the code (as I shamefully tuck my tail for posting this much code).
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Entity;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Caching;
using System.Web.Hosting;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.SessionState;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using SomeCms;
[assembly: WebActivator.PreApplicationStartMethod(typeof(Sample.Web.App_Start.cms), "PreStart")]
namespace Sample.Web.App_Start
{
public static class cms
{
public static void PreStart()
{
DynamicModuleUtility.RegisterModule(typeof(InstallerModule));
}
}
}
namespace SomeCms
{
class ActionInvokerWrapper : IActionInvoker
{
readonly IActionInvoker actionInvoker;
public ActionInvokerWrapper(IActionInvoker actionInvoker)
{
this.actionInvoker = actionInvoker;
}
public bool InvokeAction(ControllerContext controllerContext, string actionName)
{
if (actionInvoker.InvokeAction(controllerContext, actionName))
{
return true;
}
// No action method was found.
var controller = new CmsContentController();
controller.ExecuteCmsContent(controllerContext.RequestContext);
return true;
}
}
class ControllerFactoryWrapper : IControllerFactory
{
readonly IControllerFactory factory;
public ControllerFactoryWrapper(IControllerFactory factory)
{
this.factory = factory;
}
public IController CreateController(RequestContext requestContext, string controllerName)
{
try
{
var controller = factory.CreateController(requestContext, controllerName);
WrapControllerActionInvoker(controller);
return controller;
}
catch (HttpException ex)
{
if (ex.GetHttpCode() == 404)
{
return new CmsContentController();
}
throw;
}
}
static void WrapControllerActionInvoker(IController controller)
{
var controllerWithInvoker = controller as Controller;
if (controllerWithInvoker != null)
{
controllerWithInvoker.ActionInvoker = new ActionInvokerWrapper(controllerWithInvoker.ActionInvoker);
}
}
public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
{
return factory.GetControllerSessionBehavior(requestContext, controllerName);
}
public void ReleaseController(IController controller)
{
factory.ReleaseController(controller);
}
}
class InstallerModule : IHttpModule
{
static bool installed;
static readonly object installerLock = new object();
public void Init(HttpApplication application)
{
if (installed)
{
return;
}
lock (installerLock)
{
if (installed)
{
return;
}
Install();
installed = true;
}
}
static void Install()
{
Database.SetInitializer(new CreateDatabaseIfNotExists<PageContext>());
HostingEnvironment.RegisterVirtualPathProvider(new ExampleVirtualPathProvider());
WrapControllerBuilder();
AddNotFoundRoute();
AddCatchAllRoute();
}
static void WrapControllerBuilder()
{
ControllerBuilder.Current.SetControllerFactory(new ControllerFactoryWrapper(ControllerBuilder.Current.GetControllerFactory()));
}
static void AddNotFoundRoute()
{
// To allow IIS to execute "/cmscontent" when requesting something which is disallowed,
// such as /bin or /add_data.
RouteTable.Routes.MapRoute(
"CmsContent",
"cmscontent",
new { controller = "CmsContent", action = "CmsContent" }
);
}
static void AddCatchAllRoute()
{
RouteTable.Routes.MapRoute(
"CmsContent-Catch-All",
"{*any}",
new { controller = "CmsContent", action = "CmsContent" }
);
}
public void Dispose() { }
}
public class CmsContentController : IController
{
public void Execute(RequestContext requestContext)
{
ExecuteCmsContent(requestContext);
}
public void ExecuteCmsContent(RequestContext requestContext)
{
//new CmsContentViewResult().ExecuteResult(new ControllerContext(requestContext, new FakeController()));
new CmsContentViewResult().ExecuteResult(new ControllerContext(requestContext, new FakeController()));
}
// ControllerContext requires an object that derives from ControllerBase.
// NotFoundController does not do this.
// So the easiest workaround is this FakeController.
class FakeController : Controller { }
}
public class CmsContentHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
var routeData = new RouteData();
routeData.Values.Add("controller", "CmsContent");
var controllerContext = new ControllerContext(new HttpContextWrapper(context), routeData, new FakeController());
var cmsContentViewResult = new CmsContentViewResult();
cmsContentViewResult.ExecuteResult(controllerContext);
}
public bool IsReusable
{
get { return false; }
}
// ControllerContext requires an object that derives from ControllerBase.
class FakeController : Controller { }
}
public class CmsContentViewResult : ViewResult
{
public CmsContentViewResult()
{
ViewName = "index";
}
public override void ExecuteResult(ControllerContext context)
{
var request = context.HttpContext.Request;
if (request != null && request.Url != null)
{
var url = request.Url.OriginalString;
ViewData["RequestedUrl"] = url;
ViewData["ReferrerUrl"] = (request.UrlReferrer != null && request.UrlReferrer.OriginalString != url)
? request.UrlReferrer.OriginalString
: null;
}
base.ExecuteResult(context);
}
}
public class ExampleVirtualPathProvider : VirtualPathProvider
{
private readonly List<SimpleVirtualFile> virtualFiles = new List<SimpleVirtualFile>();
public ExampleVirtualPathProvider()
{
var context = new PageContext();
var pages = context.Pages.ToList();
foreach (var page in pages)
{
virtualFiles.Add(new SimpleVirtualFile(page.Path));
}
}
public override bool FileExists(string virtualPath)
{
var files = (from f in virtualFiles
where f.VirtualPath.Equals(virtualPath, StringComparison.InvariantCultureIgnoreCase) ||
f.RelativePath.Equals(virtualPath, StringComparison.InvariantCultureIgnoreCase)
select f)
.ToList();
return files.Count > 0 || base.FileExists(virtualPath);
}
private class SimpleVirtualFile : VirtualFile
{
public SimpleVirtualFile(string filename) : base(filename)
{
RelativePath = filename;
}
public override Stream Open()
{
var context = new PageContext();
var page = context.Pages.FirstOrDefault(p => p.Path == RelativePath);
return new MemoryStream(Encoding.ASCII.GetBytes(page.View), false);
}
public string RelativePath { get; private set; }
}
private class SimpleVirtualDirectory : VirtualDirectory
{
public SimpleVirtualDirectory(string virtualPath)
: base(virtualPath)
{
}
public override IEnumerable Directories
{
get { return null; }
}
public override IEnumerable Files
{
get
{
return null;
}
}
public override IEnumerable Children
{
get { return null; }
}
}
public override VirtualFile GetFile(string virtualPath)
{
var files = (from f in virtualFiles
where f.VirtualPath.Equals(virtualPath, StringComparison.InvariantCultureIgnoreCase) ||
f.RelativePath.Equals(virtualPath, StringComparison.InvariantCultureIgnoreCase)
select f).ToList();
return files.Count > 0
? files[0]
: base.GetFile(virtualPath);
}
public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
{
return IsPathVirtual(virtualPath) ? null : base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
}
private bool IsPathVirtual(string virtualPath)
{
var checkPath = VirtualPathUtility.ToAppRelative(virtualPath);
return
virtualFiles.Any(f => checkPath.StartsWith(virtualPath, StringComparison.InvariantCultureIgnoreCase)) ||
virtualFiles.Any(f => checkPath.Replace("~", "").StartsWith(virtualPath, StringComparison.InvariantCultureIgnoreCase));
}
public override bool DirectoryExists(string virtualDir)
{
return IsPathVirtual(virtualDir) || Previous.DirectoryExists(virtualDir);
}
public override VirtualDirectory GetDirectory(string virtualDir)
{
return IsPathVirtual(virtualDir)
? new SimpleVirtualDirectory(virtualDir)
: Previous.GetDirectory(virtualDir);
}
}
public class ContentPage
{
public int Id { get; set; }
public string Path { get; set; }
public string View { get; set; }
}
public class PageContext : DbContext
{
public DbSet<ContentPage> Pages { get; set; }
}
}
This question turns out to be a non-issue. My oversight of the cache dependency in the virtual path provider is returning null for virtual paths. As such, the view is cached indefinitely.
The solution is to use a custom cache dependency provider that expires immediately.
public class NoCacheDependency : CacheDependency
{
public NoCacheDependency()
{
NotifyDependencyChanged(this, EventArgs.Empty);
}
}
public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart)
{
return IsPathVirtual(virtualPath) ? new NoCacheDependency() : base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
}
Using MVVM Light, I'm trying to develop a rather simple WP7 application. I've run into a problem using the navigation service. I can navigate to a page, but after pressing the back button I can't navigate to the same page again. NavigationService throws a NullReferenceException.
I have implemented my navigation using Messaging from the GalaSoft.MvvmLight.Messaging namespace. All my views inherits from a customized PhoneApplicationPage base class that registrers a listener on "NavigationRequest":
public class PhoneApplicationPage : Microsoft.Phone.Controls.PhoneApplicationPage
{
public PhoneApplicationPage() : base()
{
Messenger.Default.Register<Uri>(this, "NavigationRequest", (uri) => NavigationService.Navigate(uri));
}
}
From my view models I post Uri's to this listener:
SendNavigationRequestMessage(new Uri("/View/AppSettingsView.xaml", UriKind.Relative));
Like i said, this works except when navigating after pressing the Back button.
Why is this and how can I solve it?
Is there a better way to implement navigation using MVVM Light?
I'm using MVVM Light as well. I have a class called PageConductor, which is based on what John Papa (Silverlight MVP) from Microsoft uses. Here's the PageConductor Service I use
public class PageConductor : IPageConductor
{
protected Frame RootFrame { get; set; }
public PageConductor()
{
Messenger.Default.Register<Messages.FrameMessage>(this, OnReceiveFrameMessage);
}
public void DisplayError(string origin, Exception e, string details)
{
string description = string.Format("Error occured in {0}. {1} {2}", origin, details, e.Message);
var error = new Model.Error() { Description = description, Title = "Error Occurred" };
Messenger.Default.Send(new Messages.ErrorMessage() { Error = error });
}
public void DisplayError(string origin, Exception e)
{
DisplayError(origin, e, string.Empty);
}
private void OnReceiveFrameMessage(Messages.FrameMessage msg)
{
RootFrame = msg.RootFrame;
}
private void Go(string path, string sender)
{
RootFrame.Navigate(new Uri(path, UriKind.Relative));
}
public void GoBack()
{
RootFrame.GoBack();
}
}
In my MainPage.xaml.cs constructor, I have this, which creates an instance of my ContentFrame in my PageConductor service.:
Messenger.Default.Send(new Messages.FrameMessage() { RootFrame = ContentFrame });
I then use dependency injection to instantiate an instance of my PageConductor Service into my MainPage ViewModel. Here is my MainViewModel class:
protected Services.IPageConductor PageConductor { get; set; }
public RelayCommand<string> NavigateCommand { get; set; }
public MainViewModel(Services.IPageConductor pageConductor)
{
PageConductor = pageConductor;
RegisterCommands();
}
private void RegisterCommands()
{
NavigateCommand = new RelayCommand<string>(
(source) => OnNavigate(source));
}
private void OnNavigate(string sender)
{
PageConductor.GoToView(sender, "main");
}
Notice the instance of my PageConductorService as a parameter in my MainViewModel constructor method. I pass this in via my ViewModelLocator:
private readonly TSMVVM.Services.ServiceProviderBase _sp;
public ViewModelLocator()
{
_sp = Services.ServiceProviderBase.Instance;
CreateMain(_sp);
}
#region MainPageViewModel
public static MainViewModel MainStatic
{
get
{
Services.ServiceProviderBase SP = Services.ServiceProviderBase.Instance;
if (_main == null)
{
CreateMain(SP);
}
return _main;
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public MainViewModel Main
{
get
{
return MainStatic;
}
}
public static void ClearMain()
{
_main.Cleanup();
_main = null;
}
public static void CreateMain(Services.ServiceProviderBase SP)
{
if (_main == null)
{
_main = new MainViewModel(SP.PageConductor);
}
}
#endregion
For further reference, my Messages.FrameMessage class is simply:
internal class FrameMessage
{
public Frame RootFrame { get; set; }
}
I've had no issues with forward/back buttons.