I am trying to share an image and a text both at the same time in xamarin.forms:
var fn = "pic.png";
var file = Path.Combine(FileSystem.CacheDirectory, fn);
File.WriteAllBytes(file, Convert.FromBase64String(image));
await Share.RequestAsync(new ShareFileRequest()
{
Title = text,
File = new ShareFile(file)
});
But this only shares the image, the title is just being ignored (well at least in anything except email, where title appears in the email subject line)
How can we fix this?
You could use DependencyService to call native share method.
In PCL:
using System;
using Xamarin.Forms;
namespace ShareSample
{
public interface IShare
{
void Share(string subject, string message, ImageSource image);
}
}
In Android project:
using Android.App;
using Android.Content;
using Android.Graphics;
using Android.OS;
using ShareSample.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: Dependency(typeof(IShareService))]
namespace ShareSample.Droid
{
public class IShareService : Activity, IShare
{
public async void Share(string subject, string message,
ImageSource image)
{
var intent = new Intent(Intent.ActionSend);
//intent.PutExtra(Intent.ExtraSubject, subject);
intent.PutExtra(Intent.ExtraText, message);
intent.SetType("image/png");
var handler = new ImageLoaderSourceHandler();
var bitmap = await handler.LoadImageAsync(image, this);
var path = Environment.GetExternalStoragePublicDirectory(Environment.DirectoryDownloads
+ Java.IO.File.Separator + "logo.png");
using (var os = new System.IO.FileStream(path.AbsolutePath, System.IO.FileMode.Create))
{
bitmap.Compress(Bitmap.CompressFormat.Png, 100, os);
}
var imageUri = FileProvider.GetUriForFile(Application.Context, "your authorities", path);
intent.PutExtra(Intent.ExtraStream, imageUri);
Forms.Context.StartActivity(Intent.CreateChooser(intent, "Share Image"));
}
}
}
define the Fileprovider in your AndroidMainfest.xml
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="app的包名.fileProvider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" />
</provider>
file_paths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<root-path name="root" path="" />
<files-path name="files" path="" />
<cache-path name="cache" path="" />
<external-path name="external" path="" />
<external-files-path name="name" path="path" />
<external-cache-path name="name" path="path" />
</paths>
In ios project:
using Foundation;
using ShareSample.iOS;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: Dependency(typeof(IShareService))]
namespace ShareSample.iOS
{
public class IShareService : IShare
{
public async void Share(string subject, string message, ImageSource image)
{
var handler = new ImageLoaderSourceHandler();
var uiImage = await handler.LoadImageAsync(image);
var img = NSObject.FromObject(uiImage);
var mess = NSObject.FromObject(message);
var activityItems = new[] { mess, img };
var activityController = new UIActivityViewController(activityItems, null);
var topController = UIApplication.SharedApplication.KeyWindow.RootViewController;
while (topController.PresentedViewController != null)
{
topController = topController.PresentedViewController;
}
topController.PresentViewController(activityController, true, () => { });
}
}
}
In PCL call DependencyService:
DependencyService.Get<IShare>().Share(" ", "Share Image with Text", img.Source);};
Related
I need to find coSpaces total="3" value from the below XML in ASP.net C#. Please help me with the xmlreader code. I have seen other tutorial where I can find element value but not this type.
Thanks,
<?xml version="1.0"?>
<coSpaces total="3">
<coSpace id="0">
<name>A</name>
<autoGenerated>false</autoGenerated>
</coSpace>
<coSpace id="2">
<name>B</name>
<autoGenerated>false</autoGenerated>
</coSpace>
<coSpace id="4">
<name>C</name>
<autoGenerated>false</autoGenerated>
</coSpace>`
</coSpaces>
You can get total in this way:
private static string GetTotal()
{
var document = new XmlDocument();
using (var file = new FileStream("file.xml", FileMode.Open))
{
using (var reader = XmlReader.Create(file))
{
while (reader.Read())
{
if (reader.IsStartElement())
{
var attr = reader["total"];
return attr;
}
}
}
}
return null;
}
Taking a minute to learn XPath, and the 2 methods that use it (SelectSingleNode, and SelectNodes) will really help in a lot of situations.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
namespace testconsole
{
class Program
{
public static string strFileName = "c:\\temp\\test.xml";
static void Main(string[] args) {
XmlDocument xml = new XmlDocument();
xml.Load(strFileName);
XmlElement ndMatch = (XmlElement) xml.SelectSingleNode("//coSpaces[#total=3]");
if (ndMatch != null) {
foreach (XmlElement ndCoSpace in ndMatch.SelectNodes("coSpace")) {
Console.Write(ndCoSpace.GetAttribute("id"));
}
} else {
Console.Write("Not found in " + strFileName);
}
}
}
}
I have a Xaml Page ListView that displays the data correctly in UWP, but does not display the data correctly in iOS. I am using HttpClient to get the data from a localhost webapi connected to SQL Server running on the local machine. I think that this has something to do with the NSUrlSession setting working with HttpClient. Any Suggestions?
This is the Xaml Page.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:telerikDataControls="clr-namespace:Telerik.XamarinForms.DataControls;assembly=Telerik.XamarinForms.DataControls"
xmlns:viewModels="clr-namespace:SxQiApp.ViewModels;assembly=SxQiApp"
xmlns:telerikListView="clr-namespace:Telerik.XamarinForms.DataControls.ListView;assembly=Telerik.XamarinForms.DataControls"
x:Class="SxQiApp.DailyCasePage">
<ContentPage.BindingContext>
<viewModels:VSxCaseViewModel />
</ContentPage.BindingContext>
<ContentPage.Content>
<telerikDataControls:RadListView x:Name="listView"
ItemsSource="{Binding SxCases}"
ItemTapped="listView_ItemTappedAsync"
SelectedItem="{Binding SelectedSxCase, Mode=TwoWay}">
<telerikDataControls:RadListView.ItemTemplate>
<DataTemplate>
<telerikListView:ListViewTemplateCell>
<telerikListView:ListViewTemplateCell.View>
<StackLayout>
<Label Text="Surgery Cases" />
<Label Text="{Binding Facesheet}" />
<Label Text="{Binding Record}" />
</StackLayout>
</telerikListView:ListViewTemplateCell.View>
</telerikListView:ListViewTemplateCell>
</DataTemplate>
</telerikDataControls:RadListView.ItemTemplate>
</telerikDataControls:RadListView>
</ContentPage.Content>
</ContentPage>
This is the code behind.
using System.Threading.Tasks;
using SxQiApp.Models;
using SxQiApp.ViewModels;
using Xamarin.Forms;
namespace SxQiApp
{
// XamlC is set in App.xaml.cs
//[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class DailyCasePage : ContentPage
{
public DailyCasePage()
{
InitializeComponent();
}
private async void listView_ItemTappedAsync(object sender, Telerik.XamarinForms.DataControls.ListView.ItemTapEventArgs e)
{
var sxcase = e.Item as SxCase;
if (sxcase != null)
{
var SxCaseViewModel = new SxCaseViewModel();
if (SxCaseViewModel != null)
{
SxCaseViewModel.SelectedSxCase = sxcase;
await Navigation.PushAsync(new EditSxCasePage(SxCaseViewModel));
}
}
}
}
}
This is the ViewModel.
using SxQiApp.Models;
using SxQiApp.Services;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
namespace SxQiApp.ViewModels
{
public class VSxCaseViewModel : INotifyPropertyChanged
{
private List<SxCase> _sxcase;
private VSxCaseDataService _vsxCaseDataService = new VSxCaseDataService();
private SxCase _selectedSxCase;
public SxCase SelectedSxCase
{
get { return _selectedSxCase; }
set
{
_selectedSxCase = value;
OnPropertyChanged();
}
}
public List<SxCase> SxCases
{
get
{
return _sxcase;
}
set
{
_sxcase = value;
OnPropertyChanged();
}
}
public ICommand AddRecordCommand => new Command(async () =>
{
await _vsxCaseDataService.PostSxCase(SelectedSxCase);
});
//public ICommand EditSxCaseCommand => new Command(async () =>
//{
// await _vsxCaseDataService.PutSxCase(SelectedSxCase);
//});
public Command EditSxCaseCommand
{
get
{
return new Command(async () =>
{
var sxCaseDataService = new SxCaseDataService();
await sxCaseDataService.PutSxCase(_selectedSxCase.Id, _selectedSxCase);
});
}
}
public VSxCaseViewModel()
{
SelectedSxCase = new SxCase();
GetSxCases();
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private async Task GetSxCases()
{
SxCases = await _vsxCaseDataService.GetSxCases();
}
}
}
This is the service code
using Newtonsoft.Json;
using SxQiApp.Models;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace SxQiApp.Services
{
class VSxCaseDataService
{
private string Url = "http://localhost:19952/api/vsxcases/";
public async Task<List<SxCase>> GetSxCases()
{
var httpClient = new HttpClient();
var json = await httpClient.GetStringAsync(Url);
var sxcases = JsonConvert.DeserializeObject<List<SxCase>>(json);
return sxcases;
}
public async Task PostSxCase(SxCase sxcase)
{
var httpClient = new HttpClient();
var json = JsonConvert.SerializeObject(sxcase);
StringContent content = new StringContent(json);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var result = await httpClient.PostAsync(Url, content);
}
public async Task PutSxCase(int sxcaseid, SxCase selectedSxCase)
{
var httpClient = new HttpClient();
var json = JsonConvert.SerializeObject(selectedSxCase);
StringContent content = new StringContent(json);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var result = await httpClient.PutAsync(Url + sxcaseid, content);
}
}
}
Try to do real clean (delete bin & obj folder) for each project & right click on solution & choose clean {your solution name}. After it is done, right click on solution again & choose rebuild {your solution name}. After all done, try to debug on iOS11 simulator/ device.
If option no.1 is not working, maybe you can try to do breakpoint in finished launching method to see is it everything is working.
If option no.2 is not working,Maybe splash screen is getting displayed for longer duration you can reduce the duration of splash screen.
Hello so I've been trying to achieve WS-Fed SSO on my MVC6 web application, I've read a bit on authentification and all to identify my requirements. I have to use WsFederationAuth so no oauth nor saml protocol would work for me.
Edit : After #Pinpoint suggestion I tried to use owin middleware to achieve the connection, but I will use the full framework DNX451 rather than DNXCore but it's something while waiting for ws-fed to be supported by Vnext.
Pinpoint adapter extension:
public static class AppBuilderExtensions
{
#if !DNXCORE50
public static IApplicationBuilder UseOwinAppBuilder(this IApplicationBuilder app,
Action<IAppBuilder> configuration)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
if (configuration == null)
{
throw new ArgumentNullException(nameof(configuration));
}
return app.UseOwin(setup => setup(next =>
{
var builder = new AppBuilder();
var lifetime = (IApplicationLifetime) app.ApplicationServices.GetService(typeof (IApplicationLifetime));
var properties = new AppProperties(builder.Properties);
properties.AppName = app.ApplicationServices.GetApplicationUniqueIdentifier();
properties.OnAppDisposing = lifetime.ApplicationStopping;
properties.DefaultApp = next;
configuration(builder);
return builder.Build<Func<IDictionary<string, object>, Task>>();
}));
}
#endif
}
And in startup.cs :
#if !DNXCORE50
app.UseOwinAppBuilder(owin =>
{
owin.UseWsFederationAuthentication(new WsFederationAuthenticationOptions
{
MetadataAddress =
"https://mysite.accesscontrol.windows.net/FederationMetadata/2007-06/FederationMetadata.xml",
Wtrealm = "http://localhost:62569/",
SignInAsAuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType,
AuthenticationType = "adfs",
SecurityTokenHandlers = new SecurityTokenHandlerCollection
{
new EncryptedSecurityTokenHandler
{
Configuration = new SecurityTokenHandlerConfiguration
{
IssuerTokenResolver = new X509CertificateStoreTokenResolver(StoreName.My,
StoreLocation.LocalMachine)
}
},
new Saml2SecurityTokenHandler
{
CertificateValidator = X509CertificateValidator.None,
}
}
});
});
#endif
I can feel I'm getting closer to a solution but it's not yet done. I have trouble in handling the token (after the authentication against the adfs)
I get this error with afaiu the token:
SecurityTokenValidationException: IDX10201: None of the the SecurityTokenHandlers could read the 'securityToken':
<Assertion ID="_851fc402-2e9c-4ff8-a743-7d65612255b9" IssueInstant="2015-06-22T16:16:03.852Z" Version="2.0" xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
<Issuer>https://mysite.accesscontrol.windows.net/</Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
<ds:Reference URI="#_851fc402-2e9c-4ff8-a743-7d65612255b9">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<ds:DigestValue>xZdzOnNIG5Ia***********t0feMWIZMLnY=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>KmuScnZBdxyaAJrfLgB9AYheUdR*****************************Xs4o8R+eMCPdWNsDjhLu500UlCgitYerjpLTTyRRdwvFo8T7LlsXO2yjv3dx83Yn+GthE+FswNRH07yIHF5wo5+/TAwiVzg+9SDbK+Nj84PdLMxwIfALAebf4/ECdpqkWvt2ligzFoQckEgZMRepOcAVfBxfELyJSUDAjnpfJCrlCQip0nykC+5R37X00flIlB563p48veeLIt0JaUdG4bwtQ8OCMg1KeD5gYix9p4E3TQ7QovN0HDoWTurLK/0H01IS73fIe6/k6DBA==</ds:SignatureValue>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<X509Data>
<X509Certificate>MIIDSjCCAjagAwIBAgIQrcBhMtovuJ**********************MDExLzAtBgNVBAMTJm1hcmdvY29uc2VpbC5hY2Nlc3Njb250cm9sLndpbmRvd3MubmV0MB4XDTE1MDYxNjA4MTYzOFoXDTIwMDUzMTIyMDAwMFowMTEvMC0GA1UEAxMmbWFyZ29jb25zZWlsLmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpeZseXX1IYTABUOPr7nfIAXc7cXAI0k+vR3qEbvy0UxEhYAkAocQR2qUTPQ8D1v4lPp59tnHKBGJ0eHt9DYm/SyKkfHsWfqsysZx5NHXSJIhy/SgHwpd8b2q1NKxqBRLrdJKyAua+WWza4p/HMFjEVoN/upZtngSqxUKO/oYqy6m7smkz8vwjzpJR8tyqN881XBQzvryiF/i3ZPFQqlCT9263TMcAGPpym9uvxHzFPPx3u8IDz3AQydyHeViaJhiXGic0VEcm6LMn3JLOYqAzJnv8z89NdpsL4ynv1ekytt/8yyza3CnsU1E4tFDj1HU3785aFZ1xm6wr1MUK9VOTAgMBAAGjZjBkMGIGA1UdAQRbMFmAEN1alzwM3lJSHdh4LFl7uxmhMzAxMS8wLQYDVQQDEyZtYXJnb2NvbnNlaWwuYWNjZXNzY29udHJvbC53aW5kb3dzLm5ldIIQrcBhMtovuJ9MilbEjMjS7TAJBgUrDgMCHQUAA4IBAQAsQ5jNKvS2fLtqs9oB6DGTXdI5nAli5UyvZUQlnfnMvgYjJKrZu79iMe9iu88cmtwZVifG14SRbVdTjUOzngIWAJ5KAQk5t//wSkwgAS+U6AFYI/mee9NLEvOEhrRbpGUP0oL504OZ9zTDeXmGu2FybRB2TvdTKLaeVsBvwqgP33QFkcuPK50fCGC1l3SecIeyWL5fsiw/2+GuTKHjCaeRqnYBgDTINptc9PGayLPBTjs4UPzbccmaYyuanmTAMZGU0iRoGJYet2uAasT52QvWZqD0NUZbWyR1N8CBf5EIW2S/TrpoOBYNgZQU5n9PRJjTBhESHXjfa8RipC8RXU9o</X509Certificate>
</X509Data>
</KeyInfo>
</ds:Signature>
<Subject>
<NameID>***********</NameID>
<SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer" />
</Subject>
<Conditions NotBefore="2015-06-22T16:16:03.836Z" NotOnOrAfter="2015-06-22T17:16:03.836Z">
<AudienceRestriction>
<Audience>http://localhost:62569/</Audience>
</AudienceRestriction>
</Conditions>
<AttributeStatement>
<Attribute Name="http://schemas.microsoft.com/identity/claims/tenantid">
<AttributeValue>********************</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name">
<AttributeValue>************</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname">
<AttributeValue>G****l</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname">
<AttributeValue>L****s</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.microsoft.com/identity/claims/identityprovider">
<AttributeValue>https://sts.windows.net/7102feaa-34af-4756-85ce-b0f69766d78d/</AttributeValue>
</Attribute>
<Attribute Name="http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider">
<AttributeValue>https://sts.windows.net/7102feaa-34af-4756-85ce-b0f69766d78d/</AttributeValue>
</Attribute>
</AttributeStatement>
<AuthnStatement AuthnInstant="2015-06-22T14:26:14.020Z">
<AuthnContext>
<AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</AuthnContextClassRef>
</AuthnContext>
</AuthnStatement>
</Assertion>
As you already figured out, the WS-Federation middleware has not been ported to ASP.NET 5 yet, but don't panic, it will definitely be: https://twitter.com/blowdart/status/610526268908535808
In the meantime, you can use the OWIN/Katana 3 WS-Federation middleware in an ASP.NET 5 application with a tiny IAppBuilder/IApplicationBuilder adapter (like this one: https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/blob/vNext/samples/Mvc/Mvc.Server/Extensions/AppBuilderExtensions.cs#L50), but of course, it won't be compatible with dnxcore50.
If you have a recent ADFS version, you could also consider switching to OAuth2.
I found out how to get claims from the http request coming back from ADFS using the prior ASP.NET classes in a way that doesn't touch web.config.
Hopefully this code is useful to someone:
using Microsoft.AspNet.Http;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Specialized;
using System.IdentityModel.Configuration;
using System.IdentityModel.Protocols.WSTrust;
using System.IdentityModel.Selectors;
using System.IdentityModel.Services;
using System.IdentityModel.Tokens;
using System.IO;
using System.Security.Claims;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel.Security;
using System.Text;
using System.Xml;
public class FederationHelper
{
public ClaimsIdentity GetClaimsIdentityFromResponse(IConfigurationRoot configurationRoot, HttpContext context)
{
var absoluteUri = string.Concat(
context.Request.Scheme,
"://",
context.Request.Host.ToUriComponent(),
context.Request.PathBase.ToUriComponent(),
context.Request.Path.ToUriComponent(),
context.Request.QueryString.ToUriComponent());
var values = new NameValueCollection();
foreach (var item in context.Request.Query)
{
values.Add(item.Key, item.Value);
}
foreach (var item in context.Request.Form)
{
values.Add(item.Key, item.Value);
}
var federation = new FederationSettings
{
AudienceUri = "http://contoso",
Endpoint = "http://sts/ls",
IssuerName = "http://sts/trust",
IssuerThumbprint = "[thumbprint]",
Realm = "https://myapp"
};
var identityConfiguration = new IdentityConfiguration(false);
identityConfiguration.AudienceRestriction.AllowedAudienceUris.Add(new Uri(federation.AudienceUri));
var issuers = new ConfigurationBasedIssuerNameRegistry();
issuers.ConfiguredTrustedIssuers.Add(federation.IssuerThumbprint, federation.IssuerName);
identityConfiguration.IssuerNameRegistry = issuers;
var tokenHandler = new SamlSecurityTokenHandler();
tokenHandler.Configuration = new SecurityTokenHandlerConfiguration();
tokenHandler.Configuration.AudienceRestriction.AudienceMode = AudienceUriMode.Always;
tokenHandler.Configuration.AudienceRestriction.AllowedAudienceUris.Add(new Uri(federation.AudienceUri));
tokenHandler.Configuration.IssuerNameRegistry = identityConfiguration.IssuerNameRegistry;
tokenHandler.Configuration.CertificateValidationMode = X509CertificateValidationMode.None;
tokenHandler.Configuration.RevocationMode = X509RevocationMode.NoCheck;
tokenHandler.Configuration.CertificateValidator = X509CertificateValidator.None;
var message = (SignInResponseMessage)WSFederationMessage.CreateFromNameValueCollection(new Uri(absoluteUri), values);
var token = CreateSecurityToken(tokenHandler, identityConfiguration, message);
var claims = tokenHandler.ValidateToken(token);
return claims[0];
}
public SecurityToken CreateSecurityToken(SamlSecurityTokenHandler handler, IdentityConfiguration configuration, SignInResponseMessage message)
{
var quotas = new XmlDictionaryReaderQuotas();
using (var reader = XmlDictionaryReader.CreateTextReader(Encoding.UTF8.GetBytes(message.Result), quotas))
{
var serializer = new WSFederationSerializer(reader);
var context = new WSTrustSerializationContext(configuration.SecurityTokenHandlerCollectionManager);
var xml = serializer.CreateResponse(message, context).RequestedSecurityToken.SecurityTokenXml.OuterXml;
return ReadToken(handler, xml, quotas);
}
}
SecurityToken ReadToken(SamlSecurityTokenHandler handler, string xml, XmlDictionaryReaderQuotas quotas)
{
using (var reader = new StringReader(xml))
{
using (var xmlReader = XmlReader.Create(reader))
{
xmlReader.MoveToContent();
return handler.ReadToken(xmlReader);
}
}
}
}
Hi want to receive push notifications on background task for that i have created Portable library here is my Background task class
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using Windows.ApplicationModel.Background;
using Windows.Data.Xml.Dom;
using Windows.Networking.PushNotifications;
using Windows.Storage;
using Windows.UI.Notifications;
namespace BackgroundTask
{
public sealed class NotificationTask : IBackgroundTask
{
public void Run(IBackgroundTaskInstance taskInstance)
{
// Get the background task details
ApplicationDataContainer settings = ApplicationData.Current.LocalSettings;
string taskName = taskInstance.Task.Name;
Debug.WriteLine("Background " + taskName + " starting...");
// Store the content received from the notification so it can be retrieved from the UI.
ToastNotification notification = (ToastNotification )taskInstance.TriggerDetails;
settings.Values[taskName] = notification.Content;
NotificationTask.AddTostNotification(notification.Content);
Debug.WriteLine("Background " + taskName + " completed!");
}
private static void AddTostNotification(String xmlDocument)
{
List<string> messageSection = NotificationTask.GetMessageAndLandingPage(xmlDocument, "toast");
if (messageSection == null) { return; }
ToastTemplateType toastTemplate = ToastTemplateType.ToastText01;
XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(toastTemplate);
XmlNodeList toastTextElements = toastXml.GetElementsByTagName("text");
toastTextElements[0].AppendChild(toastXml.CreateTextNode(messageSection[0]));
// toastTextElements[1].AppendChild(toastXml.CreateTextNode(message));
IXmlNode toastNode = toastXml.SelectSingleNode("/toast");
((XmlElement)toastNode).SetAttribute("launch", messageSection[1]);
XmlElement audio = toastXml.CreateElement("audio");
audio.SetAttribute("src", "ms-appx:///Assets/Play-Guitar.wav");
//audio.SetAttribute("loop", "true");
toastNode.AppendChild(audio);
//launch tost immediatly
ToastNotification toast = new ToastNotification(toastXml);
ToastNotificationManager.CreateToastNotifier().Show(toast);
}
Here i am registering Task
internal async void InitChannel()
{
// Applications must have lock screen privileges in order to receive raw notifications
BackgroundAccessStatus backgroundStatus = await BackgroundExecutionManager.RequestAccessAsync();
// Make sure the user allowed privileges
if (backgroundStatus != BackgroundAccessStatus.Denied && backgroundStatus != BackgroundAccessStatus.Unspecified)
{
Windows.Storage.ApplicationDataContainer roamingSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
try
{
var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
if (channel != null)
{
roamingSettings.Values["ExistingPushChannel"] = channel.Uri;
dispatcher = Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher;
channel.PushNotificationReceived += OnPushNotificationReceived;
UnregisterBackgroundTask();
RegisterBackgroundTask();
}
else
{
roamingSettings.Values["ExistingPushChannel"] = "Failed to create channel";
}
}
catch
{
roamingSettings.Values["ExistingPushChannel"] = "Failed to create channel";
}
}
}
private void RegisterBackgroundTask()
{
BackgroundTaskBuilder taskBuilder = new BackgroundTaskBuilder();
PushNotificationTrigger trigger = new PushNotificationTrigger();
taskBuilder.SetTrigger(trigger);
// Background tasks must live in separate DLL, and be included in the package manifest
// Also, make sure that your main application project includes a reference to this DLL
taskBuilder.TaskEntryPoint = "BackgroundTask.NotificationTask";
taskBuilder.Name = "PlaypushNotification";
try
{
BackgroundTaskRegistration task = taskBuilder.Register();
task.Completed += BackgroundTaskCompleted;
}
catch
{
UnregisterBackgroundTask();
}
}
private bool UnregisterBackgroundTask()
{
foreach (var iter in BackgroundTaskRegistration.AllTasks)
{
IBackgroundTaskRegistration task = iter.Value;
if (task.Name == "PlaypushNotification")
{
task.Unregister(true);
return true;
}
}
return false;
}
In my Manifest file
<Extensions>
<Extension Category="windows.backgroundTasks" EntryPoint="BackgroundTask.NotificationTask">
<BackgroundTasks>
<Task Type="pushNotification" />
</BackgroundTasks>
</Extension>
</Extensions>
PushNotification Trigger is not firing, when i debug i found that trigger property of BackgroundTaskRegistration is null. what is the issue? What wrong is going here?
I am in the middle of upgrading from umbraco v6.0.5 to v7.2.1.
In my current(v6) web.config I have the following:
<profile defaultProvider="UmbracoMemberProfileProvider" enabled="true" inherits="NFOPP.Website.usercontrols.Security.MemberProfile, NFOPP.Website">
<providers>
<clear />
<add name="UmbracoMemberProfileProvider" type="umbraco.providers.members.UmbracoProfileProvider, umbraco.providers" />
</providers>
<properties>
<clear />
<add name="_title" allowAnonymous="false" provider="UmbracoMemberProfileProvider" type="System.String" />
<add name="_firstname" allowAnonymous="false" provider="UmbracoMemberProfileProvider" type="System.String" />
<add name="_lastname" allowAnonymous="false" provider="UmbracoMemberProfileProvider" type="System.String" />
<add name="_memberNumber" allowAnonymous="false" provider="UmbracoMemberProfileProvider" type="System.String" />
</properties>
</profile>
I also have a class like this:
public class MemberProfile : ProfileBase
{
#region Firstname
private const string FIRSTNAME = "_firstname";
[SettingsAllowAnonymous(false)]
public string FirstName
{
get
{
return GetCustomProperty(FIRSTNAME);
}
set
{
SetCustomProperty(FIRSTNAME, value);
}
}
#endregion
#region Get and Set base properties
private string GetCustomProperty(string propertyName)
{
var retVal = "";
var prop = base.GetPropertyValue(propertyName);
if (prop != null)
{
retVal = prop.ToString();
}
return retVal;
}
private void SetCustomProperty(string propertyName, object value)
{
var prop = base[propertyName];
if (prop != null)
{
base.SetPropertyValue(propertyName, value);
}
}
#endregion
}
The purpose of this is so I can work with my MemberProfile object and access it's properties like FirstName directly.
The "umbraco.providers.members.UmbracoProfileProvider" does not seem to exist (unless I am mistaken) any more meaning I cannot seem to wire up a class that overrides the "ProfileBase" properly, and when I attempt to load a page that accesses the "MemberProfile" object it says that "No PropertyType exists with the supplied alias _firstname"
Is there a better way to do this, and in v7 is the config section actually needed any more if there is no provider?
Solution Implemented:
I added the following methods to my Member Profile class:
public static MemberProfile Get(IMemberService memberService, UmbracoContext context)
{
var membershipHelper = new Umbraco.Web.Security.MembershipHelper(context);
var profileModel = membershipHelper.GetCurrentMemberProfileModel();
if (profileModel != null)
{
return Get(profileModel.UserName, memberService);
}
else
{
return null;
}
}
public static MemberProfile Get(string userName, IMemberService memberService)
{
var member = memberService.GetByUsername(userName);
return new MemberProfile(member);
}
I also updated the Get and Set property methods like so:
#region Get and Set base properties
private string GetCustomProperty(string propertyName)
{
var retVal = "";
if (_member.Properties.IndexOfKey(propertyName) > -1)
{
var prop = _member.Properties[propertyName];
if (prop != null && prop.Value != null)
{
retVal = prop.Value.ToString();
}
}
return retVal;
}
private void SetCustomProperty(string propertyName, object value)
{
if (_member.Properties.IndexOfKey(propertyName) > -1)
{
var prop = _member.Properties[propertyName];
if (prop != null)
{
prop.Value = value;
}
}
}
#endregion
To use this I then called the following wherever I needed the member object:
var member = MemberProfile.Get(ApplicationContext.Current.Services.MemberService, Umbraco.Web.UmbracoContext.Current);
I would still appreciate any thoughts around this solution and how other people handle adding custom properties to the member and accessing them from code.
It's by heart, but I thought you still have the asp.net based profile provider like this:
<profile defaultProvider="UmbracoMemberProfileProvider" enabled="true" inherits= "Umbarco.Models.MemberProfile, Umbarco">
Consider using the new Membership API introduced in v7.1