Xamarin 4中ADAL组件实现及编译类型转换错误解决问询
解决Xamarin中ADAL 5.1.0的PlatformParameters参数错误问题
你遇到的这个错误是因为ADAL 5.x版本对Xamarin平台的PlatformParameters构造函数做了更新,原来直接传PromptBehavior的方式已经不再适用了——现在它需要你传入当前平台的界面上下文(Android的Activity或iOS的UIViewController),而不是枚举值,所以才会出现类型转换失败的问题。
下面是具体的解决步骤和修改后的代码:
核心问题分析
在ADAL 5.1.0中,针对Xamarin跨平台场景,PlatformParameters的构造函数已经弃用了接受PromptBehavior的重载,转而要求传入当前的界面上下文实例,因为身份验证弹窗需要绑定到当前的页面/活动才能正常显示。
修改方案
1. 确保获取到当前平台的界面上下文
- 如果是在Xamarin.Android的Activity类中调用这段代码,直接用
this即可代表当前Activity; - 如果是在Xamarin.iOS的UIViewController类中,
this就是当前的视图控制器; - 如果是在Xamarin.Forms共享代码中,需要通过依赖服务获取平台上下文(后面会给出示例)。
2. 调整代码中的PlatformParameters初始化
用条件编译适配不同平台,修改后的完整代码如下:
string cloud = "https://login.microsoftonline.com/common/oauth2"; string tenantId = App.tenantId; string authority = $"{cloud}/{tenantId}"; string clientId = App.clientId; // 恢复使用clientId,之前的注释需要去掉 Uri redirectUri = App.redirectUrl; string resource = clientId; AuthenticationResult authResult = null; AuthenticationContext authContext = new AuthenticationContext(authority); // 初始化平台参数 PlatformParameters platformParams; #if __ANDROID__ // Android平台传入当前Activity platformParams = new PlatformParameters(this); #elif __IOS__ // iOS平台传入当前UIViewController platformParams = new PlatformParameters(this); #endif try { if (authContext.TokenCache.ReadItems().Count() > 0) { authContext = new AuthenticationContext(authContext.TokenCache.ReadItems().First().Authority); authResult = await authContext.AcquireTokenSilentAsync(resource, clientId); } else { // 使用正确构造的platformParams替代原来的错误写法 authResult = await authContext.AcquireTokenAsync(resource, clientId, redirectUri, platformParams); } } catch (AdalSilentTokenAcquisitionException ee) { // 异常分支同样需要传入platformParams authResult = await authContext.AcquireTokenAsync(resource, clientId, redirectUri, platformParams); }
3. Xamarin.Forms共享代码的适配方案
如果这段代码是写在Xamarin.Forms的共享项目中,需要通过依赖服务获取平台上下文:
第一步:定义共享接口
public interface IPlatformContextProvider { object GetCurrentContext(); }
第二步:Android平台实现
在Android项目中添加实现类:
[assembly: Dependency(typeof(PlatformContextProvider))] namespace YourAppName.Droid { public class PlatformContextProvider : IPlatformContextProvider { public object GetCurrentContext() { // 使用Xamarin.Essentials获取当前Activity return Xamarin.Essentials.Platform.CurrentActivity; } } }
第三步:iOS平台实现
在iOS项目中添加实现类:
[assembly: Dependency(typeof(PlatformContextProvider))] namespace YourAppName.iOS { public class PlatformContextProvider : IPlatformContextProvider { public object GetCurrentContext() { // 获取当前根视图控制器 return UIKit.UIApplication.SharedApplication.KeyWindow.RootViewController; } } }
第四步:在共享代码中获取上下文
// 获取平台上下文 var platformContext = DependencyService.Get<IPlatformContextProvider>().GetCurrentContext(); // 构造PlatformParameters PlatformParameters platformParams; #if __ANDROID__ platformParams = new PlatformParameters((Android.App.Activity)platformContext); #elif __IOS__ platformParams = new PlatformParameters((UIKit.UIViewController)platformContext); #endif
这样就能在共享代码中正确构造PlatformParameters,解决类型转换的问题了。
内容的提问来源于stack exchange,提问作者Akoh Victor Gutz
相关产品推荐
相关产品推荐

