System.MissingMethodException When Sending Email using MailKit In Xamarin.Forms - xamarin.forms

I am trying to use the MailKit library to send email in Xamarin.Forms. However, I am getting the following exception when execution hits the ConnectAsync() method:
System.MissingMethodException: string[] string.Split(char,System.StringSplitOptions) occurred
Has anyone encountered this before. I am unaware of any missing methods.
Following is my code in .net standard project:
using MailKit.Net.Smtp;
using MimeKit;
using MimeKit.Text;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
public async Task SendAsync(EmailMessage emailMessage)
{
try
{
var message = new MimeMessage();
message.To.Add(new MailboxAddress("Recipient", "xamapp#icloud.com"));
message.From.Add(new MailboxAddress("Sender", "xamapp.no.reply#gmail.com"));
message.Subject = "Test!!";
message.Body = new TextPart(TextFormat.Html)
{
Text = "Test message"
};
using (var emailClient = new SmtpClient())
{
await emailClient.ConnectAsync("smtp.gmail.com", 465, true);
emailClient.AuthenticationMechanisms.Remove("XOAUTH2");
await emailClient.AuthenticateAsync("username", "password");
await emailClient.SendAsync(message);
emailClient.Disconnect(true);
}
}
catch (SmtpCommandException ex)
{
Debug.WriteLine($"Error sending email: {ex.Message}");
Debug.WriteLine($"StatusCode: {ex.StatusCode}");
}
catch (SmtpProtocolException ex)
{
Debug.WriteLine($"Protocol error while sending email: {ex.Message}");
}
}

Sounds like your Xamarin.Forms project is pulling in mismatched .NET framework versions of libraries (probably the wrong MimeKit and/or MailKit framework versions).
Check to see which exact MimeKit and MailKit assemblies your build is pulling in from the nuget packages. In case you aren't familiar with how nugets work, each nuget can contain multiple copies of the library that is built for different frameworks.
For example, the MimeKit nuget has assemblies built for the following frameworks:
netstandard1.3
netstandard1.6
netstandard2.0
Xamarin.Android
Xamarin.iOS
net45
portable-net45+win8 (Profile7)
portable-net45+win8+wpa81 (Profile111)
And the MailKit nuget contains assemblies built for the following frameworks:
netstandard1.3
netstandard1.6
netstandard2.0
Xamarin.Android
Xamarin.iOS
net45
portable-net45+win81+wpa81 (Profile32)
Make sure that your project is pulling in the netstandard2.0 assemblies for both nugets and not a mix and match.

Related

Is it possible to integrate AdMob in an Android app using Uno Platform

I have a few UWP apps I would like to migrate to Android.
I already migrated some using Xamarin.Forms
I have discovered Uno Platform that seems to be great. But I didn't find any information about integration AdMob advertisement in an Android project using Uno Platform.
Has anyone done it already?
Yes, it is possible and I have been able to get it working in my Uno Platform app on Android and iOS. I am planning to write a blogpost about getting AdMob and AdSense running on Android, iOS and WASM, and publish a Uno Platform library on NuGet that will do all the heavy lifting for you, so stay tuned :-) .
For now, here is a unedited, raw version of the control I am using currently. It requires that you install the Google Play Services Ads NuGet packages in the Android project and in the iOS project.
Android
#if __ANDROID__
using Android.Gms.Ads;
using Android.Widget;
using System;
using System.Collections.Generic;
using System.Text;
using Uno.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace SmsTicket.Core.Controls
{
public partial class AdControl : ContentControl
{
public AdControl()
{
var adView = new AdView(ContextHelper.Current);
adView.AdSize = AdSize.SmartBanner;
adView.AdUnitId = "YOUR AD UNIT ID";
HorizontalContentAlignment = HorizontalAlignment.Stretch;
VerticalContentAlignment = VerticalAlignment.Stretch;
var adParams = new LinearLayout.LayoutParams(
LayoutParams.WrapContent, LayoutParams.WrapContent);
adView.LayoutParameters = adParams;
adView.LoadAd(new AdRequest.Builder().AddTestDevice("YOUR TEST DEVICE ID").Build());
Content = adView;
}
}
}
#endif
iOS
#if __IOS__
using Google.MobileAds;
using System;
using System.Collections.Generic;
using System.Text;
using UIKit;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml;
using CoreGraphics;
namespace SmsTicket.Core.Controls
{
public partial class AdControl : ContentControl
{
public AdControl()
{
HorizontalContentAlignment = HorizontalAlignment.Stretch;
VerticalContentAlignment = VerticalAlignment.Stretch;
Background = SolidColorBrushHelper.Red;
Width = AdSizeCons.LargeBanner.Size.Width;
Height = AdSizeCons.LargeBanner.Size.Height;
Windows.UI.Xaml.Window.Current.Activated += Current_Activated;
}
private void LoadAd()
{
if (!(Content is BannerView))
{
var adView = new BannerView(AdSizeCons.LargeBanner)
{
AdUnitID = "YOUR AD UNIT ID",
RootViewController = GetVisibleViewController()
};
adView.LoadRequest(GetRequest());
Content = adView;
}
}
Request GetRequest()
{
var request = Request.GetDefaultRequest();
// Requests test ads on devices you specify. Your test device ID is printed to the console when
// an ad request is made. GADBannerView automatically returns test ads when running on a
// simulator. After you get your device ID, add it here
request.TestDevices = new[] { Request.SimulatorId.ToString(), "YOUR TEST DEVICE ID" };
return request;
}
UIViewController GetVisibleViewController()
{
UIViewController rootController;
if (UIApplication.SharedApplication.KeyWindow == null)
{
return null;
}
else
{
rootController = UIApplication.SharedApplication.KeyWindow.RootViewController;
}
if (rootController.PresentedViewController == null)
return rootController;
if (rootController.PresentedViewController is UINavigationController)
{
return ((UINavigationController)rootController.PresentedViewController).VisibleViewController;
}
if (rootController.PresentedViewController is UITabBarController)
{
return ((UITabBarController)rootController.PresentedViewController).SelectedViewController;
}
return rootController.PresentedViewController;
}
private void Current_Activated(object sender, Windows.UI.Core.WindowActivatedEventArgs e)
{
LoadAd();
}
}
}
#endif
Also make sure to include the Ad control only conditionally (as I have provided only Android and iOS version here).
Uno Platform won't block you from using any third party (especially not on mobile). If there is a xamarin binding you can use it as-is in your code, just like you would use it in a Xamarin.Forms app. If it's a library affecting the view you will most likely create a custom control and interact with the third-party classes via C#.
If there's no xamarin binding for a library, you can create one following microsoft documentation.
Good news! For admob there is a microsoft-supported binding nuget and it has been used in an uno application in the past.

Error on inserting into SQLite table with Xamarin iOS

I have a Xamarin Forms application that works fine on Android, but when I run on iOS, I get this error when I set up the database
Method not found: string SQLitePCL.raw.sqlite3_column_name(SQLitePCL.sqlite3_stmt,int)
and then when I try to insert into the database table
Method not found: string SQLitePCL.raw.sqlite3_errmsg(SQLitePCL.sqlite3)
The application uses mvvmlight and I have the sqlite-net-pcl package installed there and also in the platform code. The versions all marry up.
My iOS initialising code for sqlite looks like this (on the platform)
public class SQLiteConnectionFactory : ISqliteConnectionFactory
{
readonly string Filename = "mydb";
public SQLiteConnection GetConnection()
{
var path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
path = Path.Combine(path, Filename);
SimpleIoc.Default.Register<ISqliteConnectionFactory, SQLiteConnectionFactory>();
return new SQLiteConnection(path, SQLiteOpenFlags.Create | SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.SharedCache);
}
and the insert code (in the mvvmlight project) like this
public void SaveListData<T>(List<T> toStore)
{
try
{
lock (dbLock)
{
connection.InsertAll(toStore);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
I've had issues with Xam.Android and sqlite-net-pcl, but never on iOS
I have the sqlite-net-pcl 1.7.302-beta and SQLitePCL.* 2.0.2 packages installed (using the beta version to prevent some of the linking issues on the stable version)
Below is a shot of the iOS packages installed
Downgrade your sqlite-net-pcl package to version 1.5.231, that did the job for me

ConvertApi NuGet Package Error: Could not install package 'ConvertApi 2.7.0'

I am Adding ConvertApi nuget package to Convert PDF to Doc file,
But getting below Error
Could not install package 'ConvertApi 2.7.0'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.6.1', but the package does not contain any assembly references or content files that are compatible with that framework.
Note:
You can Suggesst some other API's as well to achieve the above task.
The ConvertApi 2.7.0 NuGet package is .NET Core 2 version library and can be installed on .NET 4.7 or higher. However, you can use plain C# implementation to call ConvertAPI REST API, the example below use WebClient to send an MS Word file for conversion to PDF document.
using System;
using System.Net;
using System.IO;
class MainClass {
public static void Main (string[] args) {
const string fileToConvert = "test.docx";
const string fileToSave = "test.pdf";
const string Secret="";
if (string.IsNullOrEmpty(Secret))
Console.WriteLine("The secret is missing, get one for free at https://www.convertapi.com/a");
else
try
{
Console.WriteLine("Please wait, converting!");
using (var client = new WebClient())
{
client.Headers.Add("accept", "application/octet-stream");
var resultFile = client.UploadFile(new Uri("http://v2.convertapi.com/convert/docx/to/pdf?Secret=" + Secret), fileToConvert);
File.WriteAllBytes(fileToSave, resultFile );
Console.WriteLine("File converted successfully");
}
}
catch (WebException e)
{
Console.WriteLine("Status Code : {0}", ((HttpWebResponse)e.Response).StatusCode);
Console.WriteLine("Status Description : {0}", ((HttpWebResponse)e.Response).StatusDescription);
Console.WriteLine("Body : {0}", new StreamReader(e.Response.GetResponseStream()).ReadToEnd());
}
}
}

Unity InterfacesInterceptor in .NET Core

I'll start out with the questions first and follow up with context:
Is there a version of Unity.Interception available that is compatible with .NET Core?
Is there a .NET Core compatible alternative to Unity.Interception?
I am looking at using the Microsoft.Practices.Unity.InterceptionExtension.InterfaceInterceptor to short-circuit calls to certain interfaces (example code below), but it seems that the suggested NuGet package, Unity.Interception 4.0.1, is not compatible with .NET Core.
I have made an attempt to shoe-horn in the usage of Unity.Interception 4.0.1, as the code snippets used works fine in classic .NET; but as mentioned I am running into problems with .NET Core:
Install-Package : Package Unity.Interception 4.0.1 is not compatible with netcoreapp1.1 (.NETCoreApp,Version=v1.1). Package Unity.Interception 4.0.1 supports: net45 (.NETFramework,Version=v4.5
)
I tried to circumvent this by adding net451 to the PackageTargetFallback list:
<PackageTargetFallback>$(PackageTargetFallback);net451;dnxcore50;portable-net451+win8</PackageTargetFallback>
This allowed me to install the package, but it then complains something fierce about needing a reference to mscorlib:
Error CS0012
The type 'Type' is defined in an assembly that is not referenced. You must add a reference to assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
I'm not going to attempt to reference in the Classic .NET framework into a .NET Core application, so I'm pretty much at a dead end here.
Example code:
public class Interceptions
{
public static object CreateCustomInterceptedProxy(Type type)
{
var interceptor = new InterfaceInterceptor();
var proxy = interceptor.CreateProxy(type, null);
var interceptionBehavior = new CustomInterceptionBehavior();
proxy.AddInterceptionBehavior(interceptionBehavior);
return proxy;
}
}
public class CustomInterceptionBehavior : IInterceptionBehavior
{
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
object response = null; // replace with stuff that builds an actual object
return input.CreateMethodReturn(response, new object[] { });
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public bool WillExecute => true;
}
I know the question is for around a month ago, but I thought it might be useful for other developers as well (because It's been a nightmare for me).
I have forked out Unity project and ported that to .Net Core 2.0. You can find it under this repository:
https://github.com/Chavoshi/Unity.NetCore
And also these are the nuget packages:
https://www.nuget.org/packages/Unity.NetCore/
https://www.nuget.org/packages/Unity.Interception.NetCore/
P.S: The only part which I was not able to port is TransparentProxyInterception that uses .Net Remoting which is totally discontinued in .Net Core.
Unfortunately you have to use 3rd party libraries like:
Unity fork: https://www.nuget.org/packages/Unity.Interception.NetCore/
Dora Interception: https://www.nuget.org/packages/Dora.Interception/ it has a detailed usage documentation here.
It seems Castle.Core's DynamicProxy is what I needed:
using Castle.DynamicProxy;
public class CustomInterceptor : IInterceptor
{
public static object CreateCustomInterceptedProxy(Type type)
{
var proxyGenerator = new ProxyGenerator();
var interceptor = new Interceptor();
var proxy = proxyGenerator.CreateInterfaceProxyWithoutTarget(type, interceptor);
return proxy;
}
}
public class CustomInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
object returnValue; // Do stuff to populate return value
invocation.ReturnValue = returnValue;
}
}

SQLite-net PCL and Xamarin.Forms

I have a problem with this Nuget Package:
https://www.nuget.org/packages/sqlite-net-pcl/1.0.11
In my test Case I have a PCLLibrary called "PCL" with this NuGet Package. And an emtpy class which has
using SQLite;
namespace PCL
{
public class Test
{
}
}
Now I create a new Xamarin.Forms PCL Project and reference this Library
using System;
using Xamarin.Forms;
namespace PCL
{
public class App : Application
{
public App ()
{
// The root page of your application
MainPage = new ContentPage {
Content = new StackLayout {
VerticalOptions = LayoutOptions.Center,
Children = {
new Label {
XAlign = TextAlignment.Center,
Text = "Welcome to Xamarin Forms!"
}
}
}
};
var test = new Test();
}
}
}
Now I run my App in iOS Simulator and it gets killed ...
When i am not creating an instance of Test this App starts fine...
When I integrate this Package directly in my Forms Library, I can use it normally.
What can cause this?
Normally when you are dealing with NuGet packages on PCL's you need to add the NuGet package on the iOS project as well as the PCL. This is because it may have some platform specific code in it (will definitely be the case with a SQLite library).
When you add it to the iOS project it loads the specific assemblies for iOS that is needed. Its just something you need to be aware of.
Also I would recommend this package: https://www.nuget.org/packages/SQLite.Net-PCL/

Resources