Xamarin Forms UWP Missing Phone Call Manager Assembly - c#

PROBLEM
Working through Xamarin University course XAM120. Reached a blocker in adding my IDial implementation to my UWP project. For some reason my project is not picking up the PhoneCallManager API on my system.
Error:
Error CS1069
The type name 'PhoneCallManager' could not be found in the namespace 'Windows.ApplicationModel.Calls'. This type has been forwarded to assembly 'Windows.Foundation.UniversalApiContract, Version=3.0.0.0, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime' Consider adding a reference to that assembly.
Code:
using System.Threading.Tasks;
using Windows.Foundation.Metadata;
using Phoneword.UWP;
using Xamarin.Forms;
namespace Phoneword.UWP
{
public class PhoneDialer : IDialer
{
public Task<bool> DialAsync(string phoneNumber)
{
if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.Calls.CallsPhoneContract", 1, 0))
{
Windows.ApplicationModel.Calls.PhoneCallManager.ShowPhoneCallUI(phoneNumber, "Phoneword");
return Task.FromResult(true);
}
return Task.FromResult(false);
}
}
}

Add the following reference to your UWP project:

Don't forget to enable the Phone Dialer capabilities in UWP.

For Dependency Injection to work in Xamarin you need to tell it to couple your class with the correct interface!
So above your namespace Phoneword.UWP line place following
[assembly: Xamarin.Forms.Dependency (typeof (PhoneDialer))]
Look at the tutorial in the docs : https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/dependency-service/introduction/#Registration

Related

How to get IMEI number in C# xamarin forms android?

I'm working with C# xamarin forms android and I'm trying to get the IMEI number. I've been searching about it and everything I found doesn't works. Now I'm trying with this code but again, Doesn't works.
Errors:
The name settings does not exist in the current context.
The name Forms does not exist in the current context.
C# code:
[assembly: Xamarin.Forms.Dependency(typeof(UniqueIdAndroid))]
namespace AppMobile.Models
{
public class UniqueIdAndroid
{
public string GetIdentifier()
{
return Settings.Secure.GetString(Forms.Context.ContentResolver, Settings.Secure.AndroidId);
}
}
}
Somebody knows how could I resolve this or knows other solution? Thank you very much!
UPDATE 1
c# code:
using Android.OS;
using AppMobile.Models;
using System;
using System.Collections.Generic;
using System.Text;
using static Android.Provider.Settings;
using Android.Provider;
using Xamarin.Forms;
[assembly: Xamarin.Forms.Dependency(typeof(UniqueIdAndroid))]
namespace AppMobile.Models
{
public class UniqueIdAndroid : IDevice
{
public string GetIdentifier()
{
return Settings.Secure.GetString(Forms.Context.ContentResolver, Settings.Secure.AndroidId);
}
}
}
I have added the IDevice interface that I don't know really what it should be and I fixed the settings problem with using Android.Provider;.
this link shows that I have to call with this:
string deviceIdentifier = DependencyService.Get<IDevice>().GetIdentifier();
But i don't understand how to implement IDevice interface.
Someone can help me? Thank you very much!
UPDATE 2
so, now I can use the function.
C# code:
using Android.OS;
using AppMobile.Models;
using System;
using System.Collections.Generic;
using System.Text;
using static Android.Provider.Settings;
using Android.Provider;
using Xamarin.Forms;
using Android.Content;
[assembly: Xamarin.Forms.Dependency(typeof(UniqueIdAndroid))]
namespace AppMobile.Models
{
public class UniqueIdAndroid
{
public string GetIdentifier()
{
//return Settings.Secure.GetString(Forms.Context.ContentResolver, Settings.Secure.AndroidId);
return Settings.Secure.GetString(Android.App.Application.Context.ContentResolver, Settings.Secure.AndroidId);
}
}
}
My problem is that this doesn't give me the IMEI. Insted it gives me the ID of the phone, ¿is there some way to get the IMEI string? Thank you very much!
You can try the following code:
Android.Telephony.TelephonyManager mTelephonyMgr;
mTelephonyMgr = (Android.Telephony.TelephonyManager)Android.App.Application.Context.GetSystemService(Android.Content.Context.TelephonyService);
string imei = mTelephonyMgr.GetMeid(0);
And from android document getMeid, we know that :
Starting with API level 29, persistent device identifiers are guarded
behind additional restrictions, and apps are recommended to use
resettable identifiers (see Best practices for unique identifiers).
This method can be invoked if one of the following requirements is
met:
If the calling app has been granted the READ_PRIVILEGED_PHONE_STATE permission; this is a privileged permission that can only be granted
to apps preloaded on the device.
If the calling app is the device owner of a fully-managed device, a profile owner of an organization-owned device, or their delegates
(see DevicePolicyManager.getEnrollmentSpecificId()).
If the calling app has carrier privileges (see hasCarrierPrivileges()) on any active subscription.
If the calling app is the default SMS role holder
Note:
In general, you can't get READ_PRIVILEGED_PHONE_STATE permission. It's only available to privileged system apps. Unless this is a personal app and you have a rooted device so you can make your app a privileged system app.
For more information, you can check document getMeid.

Unittesting Azure System.IO.FileLoadException: Could not load file or assembly 'System.Text.Json'

I have a library that retrieves secrets from Azure. I can use it without a problem from a console app, but when I use it from unittest, I get an error:
Test method UnitTests.UnitTest1.TestCredentials threw exception:
System.IO.FileLoadException: Could not load file or assembly
'System.Text.Json, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The
located assembly's manifest definition does not match the assembly
reference. (Exception from HRESULT: 0x80131040)
at Common.Credentials.GetDbConnStr(String databaseName) at UnitTests.UnitTest1.TestCredentials()
using System;
using System.Configuration;
using System.Text.Json;
using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
namespace Common
{
public class Credentials
{
public static string GetDbConnStr(string databaseName)
{
string keyVaultUrl = "https://cat.vault.azure.net/";
Console.WriteLine($"Retrieving credentials for {databaseName}");
var client = new SecretClient(new Uri(keyVaultUrl), new DefaultAzureCredential());
var res = client.GetSecret("conn");
return res.Value.Value.ToString() + $"Database={databaseName}";
}
}
}
and here is the test:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Net;
using System.Data.SqlClient;
using Common;
namespace UnitTests
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestCredentials()
{
string conn_str = Credentials.GetDbConnStr("test");
}
}
}
Note that I can see System.Text.Json.dll in the bin/Debug folder of the test project.
Thanks to Anand Sowmithiran who posted the comment
Check your versions of Function runtime, .NET, etc. - refer this Github issue
I upgraded System.Text.Json to version 6.0.2 as suggested in the issue and the problem went away.
I fixed this issue at my end by installing the nuget package with latest version of System.Text.Json

HttpClient has no definition for GetJsonAsync

I'm currently tapping into Blazor, and want to move my code so it's more readable and reusable. In my razor component, the Method works flawlessly - in a Class, it doesn't.
In my component, I can simply use this:
response = await Http.GetJsonAsync<T>(Uri);
In my Class, Visual Studio complains that System.Net.Http's HttpClient contains no definition for GetJsonAsync - but I'm getting a typed response, so I want to deserialize it properly.
As of preview 8, you need:
<PackageReference Include="Microsoft.AspNetCore.Blazor.HttpClient" Version="3.0.0-preview8.19405.7" PrivateAssets="all" />
NOTE: This was correct at the time, but as of Blazor version 3.1.0 this may have changed again so that now you most likely want the System.Net.Http.Json package. See the answer from #JohnB below.
Great question. And I'm assuming Darrell's answer (and the others) was 100% correct as of version 3.0.0 (Blazor WebAssembly preview).
However, as for version 3.1.301 I think the package location has changed.
Currently, the namespace is: System.Net.Http.Json
That will give you access to: HttpClientJsonExtensions
A. If you want to put that code into a separate class within your Blazor WebAssembly project, all you need is to put this at the top of your class file:
using System.Net.Http; // for HttpClient
using System.Net.Http.Json; // for HttpClientJsonExtensions
B. If you want to put that class into a separate project (.NET Core library) then you need to add the NuGet package also:
NuGet package: System.Net.Http.Json
Then you can use it in your class like in the example below. Obviously these extension methods are doing serialization, but what's interesting is that the package doesn't depend on Newtonsoft.Json because it uses the new System.Text.Json instead.
using System;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;
namespace MyClassLibrary
{
public class MyClass
{
public async Task MyMethod()
{
string baseAddress = "http://localhost:57012/";
var httpClient = new HttpClient() { BaseAddress = new Uri(baseAddress) };
var myPocos = await httpClient.GetFromJsonAsync<MyPoco[]>("api/mypocos");
foreach (var myPoco in myPocos)
Console.WriteLine($"Id: {myPoco.Id}, Name: {myPoco.Name}");
}
}
public class MyPoco
{
public int Id { get; set; }
public string Name { get; set; }
}
}
Article about System.text.json VS Newtonsoft.json versus Utf8Json.
As of today the correct answer is:
using System.Net.Http.Json
and
GetFromJsonAsync()
Just download Microsoft.AspNetCore.Blazor.HttpClient package.
It's worth noting that "include prerelease" must be checked in order to find this package. I just spent a half hour getting fairly angry that the package wasn't found and scouring google to find out why!
For Blazor, there is an extension class (Microsoft.AspNetCore.Blazor.HttpClientJsonExtensions) available to get you the same extension methods.
Ref: https://learn-blazor.com/architecture/rest-api/

Why I cannot use HttpResponseMessage class?

I'm new to ASP.NET Web API and want to make HttpResponseMessage instance from a utility class I made. Then I made very simple class.
But following compile error occurred.
CS0246: The type or namespace name 'HttpResponseMessage' could not be
found (are you missing a using directive or an assembly reference?)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Web;
namespace myapplication.App_Code.Utils
{
public class HttpUtility
{
// compile error here
public HttpResponseMessage GetHttpResponseMessage ()
{
return new HttpResponseMessage();
}
}
}
HttpResponseMessage is available from Controller Class which was made automatically by ASP.NET but not my Utility class.
What am I missing?
I have noticed that you placed your class in App_Code folder in your project. This folder has a special purpose in ASP.NET world and should be used for shared classes and business objects that you want to compile as part of your application. So either move your class into another folder, or change its Build Action in properties section to Compile.

ASP.NET vNext DataAnnotations DatabaseGenerated not working

I'm trying define a model ID variable like this in ASP.NET 5:
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
To support data annotations I've added the package System.ComponentModel.DataAnnotations in my project.json file like this:
"System.ComponentModel.Annotations": "4.0.10-beta-22811"
And in the model cs file I've added using System.ComponentModel.DataAnnotations.Schema;
Though I get the following error:
Error CS0433 The type 'DatabaseGeneratedAttribute' exists in both 'System.ComponentModel.Annotations, Version=4.0.10.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' and 'System.ComponentModel.DataAnnotations, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
And I don't know how I should fix this really. I've tried to include the namespace System.ComponentModel.Annotations instead of System.ComponentModel.DataAnnotations but it seems like it doesn't exist as I get this error then:
Error CS0234 The type or namespace name 'Annotations' does not exist in the namespace 'System.ComponentModel' (are you missing an assembly reference?)
And if that namespace does not exist I don't understand how I can get the previous error which tells me that DatabaseGeneratedAttribute exists in two places.
I would really appreciate all help I can get with this.
You can just use the KeyAttribute. That should do the auto generation for you.
[Key]
public int Id { get; set; }
This attribute is available in the System.ComponentModel.DataAnnotations namespace
However, if you want to continue using the DatabaseGeneratedAttribute. The error is pretty self explanatory. It tells you that it is available in both namespaces
System.ComponentModel.DataAnnotations
System.ComponentModel.DataAnnotations.Schema
You will need to explicity state the namespace you need to use E.g.
[System.ComponentModel.DataAnnotations.Schema.DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
You can always use an alias to keep the namespace short and sweet.
Please check that your project does not have reference to both version of System.ComponentModel.DataAnnotations.dll assembly.
Old version (4.0.0.0) can be included to your project by default, and do not be removed after you install package with new version (4.0.10.0).

Categories