我有一对使用Dropnet进行Dropbox集成的Windows Phone应用程序。一个在Visual Studio Express 2012中开发,目标是7.1,一个在Visual Studio 2013中开发,目标是8.0。
两者都通过NuGet使用Dropnet 1.9.6和RestSharp 104.4.0。
7.1项目使用以下静态类与DropNet身份验证进行交互(以及文件操作,但为了清楚起见,我已将其排除在外)。
public static class DropboxStorage
{
const string UserToken = "UserToken";
const string UserSecret = "UserSecret";
private static DropNetClient _Dropbox;
public static DropNetClient Dropbox
{
get
{
if (_Dropbox == null)
{
_Dropbox = new DropNetClient(AppKey, AppSecret);
if (IsAuthenticated)
{
_Dropbox.UserLogin = new UserLogin
{
Token = (string)IsolatedStorageSettings.ApplicationSettings[UserToken],
Secret = (string)IsolatedStorageSettings.ApplicationSettings[UserSecret]
};
}
_Dropbox.UseSandbox = true;
}
return _Dropbox;
}
}
public static bool IsAuthenticated
{
get
{
return IsolatedStorageSettings.ApplicationSettings.Contains(UserToken) &&
IsolatedStorageSettings.ApplicationSettings.Contains(UserSecret);
}
}
public static void StartAuthentication(Action<Uri> success, Action<Exception> failure)
{
Dropbox.GetTokenAsync(userLogin =>
{
var url = Dropbox.BuildAuthorizeUrl(userLogin);
if (success != null) success(new Uri(url, UriKind.RelativeOrAbsolute));
}, error =>
{
if (failure != null) failure(error);
});
}
public static void CheckAuthentication(Uri uri, Action success, Action<Exception> failure)
{
if (uri.LocalPath == "/1/oauth/authorize_submit")
{
Dropbox.GetAccessTokenAsync((accessToken) =>
{
IsolatedStorageSettings.ApplicationSettings[UserToken] = accessToken.Token;
IsolatedStorageSettings.ApplicationSettings[UserSecret] = accessToken.Secret;
IsolatedStorageSettings.ApplicationSettings.Save();
if (success != null) success();
},
(error) =>
{
if (failure != null) failure(error);
});
}
}
然后通过带有WebBrowser控件的页面访问它。
XAML
<phone:WebBrowser x:Name="Browser"
IsScriptEnabled="True"
Navigated="Browser_Navigated"/>
C#
public partial class DropboxPage : PhoneApplicationPage
{
public DropboxPage()
{
InitializeComponent();
DropboxStorage.StartAuthentication(
uri => Browser.Navigate(uri),
ex => ShowException(ex));
}
public void Browser_Navigated(object sender, NavigationEventArgs e)
{
Debug.WriteLine(e.Uri.OriginalString);
DropboxStorage.CheckAuthentication(
e.Uri,
() => NavigationService.GoBack(),
ex => ShowException(ex));
}
private void ShowException(Exception e)
{
MessageBox.Show(e.Message);
NavigationService.GoBack();
}
}
显示Dropbox身份验证网页
,当Dropbox网址包含/1/oauth/authorize_submit
时,代码确定身份验证成功。
这一切都很完美,但8.0项目的表现略有不同。
第一个区别是BuildAuthorizeUrl
来电返回的网址。
https://www.dropbox.com/1/oauth/authorize?oauth_token=<token>
https://api.dropbox.com/1/oauth/authorize?oauth_token=<token>
第二个区别是,一旦应用程序连接,Dropbox网址就不会从/authorize?oauth_token=
更改为/authorize_submit
,因此永远不会调用GetAccessTokenAsync
用户令牌和用户秘密没有存储。
我迄今为止的调查提出了几种解决这个问题的方法
GetAccessTokenAsync
电话周围移除网址验证
并吃掉生成的DropboxExceptions BuildAuthorizeUrl
电话中添加回调网址。我目前正在做的事情1.只是为了让事情顺利进行,但显然这不是一个长期的解决方案。我宁愿避免使用回调网址,因为它似乎对移动应用程序来说过于复杂。
我之后的目标是让8.0项目的行为方式与7.1项目相同。我已经查看了Dropnet源代码,其中包含https://api.dropbox.com作为它的基本网址,因此我对第一代7.1代码的工作原理更加清晰
答案 0 :(得分:1)
行为的差异是由8.0项目引起的,该项目使用System.Windows.Interactivity将Navigated事件转换为对ViewModel上的Command的调用。这似乎阻止网站和WebBrowser控件正确交互并重定向到https://www.dropbox.com。
当前强>
XAML
<phone:WebBrowser x:Name="Browser"
IsScriptEnabled="True"
Visibility="{Binding IsAuthenticated, Converter={StaticResource BoolToInvisibilityConverter}}"
Source="{Binding AuthenticateUri}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Navigated" >
<i:InvokeCommandAction Command="{Binding BrowserNavigated}"
CommandParameter="{Binding Source, ElementName=Browser}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</phone:WebBrowser>
C#
BrowserNavigated = new RelayCommand<Uri>(u =>
{
RemoteStorage.CheckAuthentication(u, () => IsAuthenticated = true, ex => ShowException(ex));
});
<强>校正的强>
XAML
<phone:WebBrowser x:Name="Browser"
IsScriptEnabled="True"
Visibility="{Binding IsAuthenticated, Converter={StaticResource BoolToInvisibilityConverter}}"
Source="{Binding AuthenticateUri}"
Navigated="Browser_Navigated"/>
C#
private void Browser_Navigated(object sender, NavigationEventArgs e)
{
ViewModel.BrowserNavigated.Execute(e.Uri);
}
在这两种情况下,绑定到WebBrowser Source的视图模型的AuthenticateUri属性由DropboxStorage类中的StartAuthentication方法设置。
添加事件处理程序后,8.0项目按预期工作。
答案 1 :(得分:0)
不久前我也开始看到这个问题了。直到那时我的应用程序在WP8上运行良好。我不记得所有的细节,但我看了我的签到修复它,我认为第一个网址的额外页面加载开始发生。 Dropbox没有关于更改的警告。
为了解决这个问题,我等待某个网址出现在LoadCompleted
事件中。您使用我认为也应该有效的Navigated
事件。
我会像这样修改你的事件处理程序:
public void Browser_Navigated(object sender, NavigationEventArgs e)
{
if (e.Uri.AbsolutePath == "/1/oauth/authorize_submit")
{
DropboxStorage.CheckAuthentication(
e.Uri,
() => NavigationService.GoBack(),
ex => ShowException(ex));
}
}