Silverlight 4 Get Current User - silverlight

I have seen this question posed regarding Silverlight 2 but I have not seen any questions about Silverlight 4.
Is there a way to get the current user running an application in Silverlight 4.0? I thought I remember seeing that as one of the features of 4.0 but I cannot find it. (Maybe it was just wishful thinking on my part.) I would imagine it would have to come from the OS running the browser or the browser itself. (The application is not being installed locally, it's running in the browser)
I have a solution where I call web service method that just does the following to get the users name. However, I would like to not have to call a web service
HttpContext.Current.User.Identity.Name.ToUpper();
Thanks in advance!

Getting the Username client-side in standard Inbrowser silverlight app just isn't going to happen, it would be a really bad thing security wise if it were possible.
Personally if I had this requirement I would probably use some web service, WCF or a simple IHttpHandler server-side. However I would be in inclined to call it something like "UserContext" and send XML. The XML would contain the Username. This would allow for additional user specific state to be added to the XML later as further requirements become clear. Adding these new chunks of info would be easy.

You might find it easier just to pass the name into the silverlight app as a parameter

In your Silverlight object tag add a new param with name as initParam (note the casing). Through this you can pass values as key=value[,key=value,...] pairs.
Here I am passing a key of usrIdentity and value as the Current User Identity Name.
<param name="initParams" value='usrIdentity=#HttpContext.Current.User.Identity.Name'/>
In your App.xaml.cs in the Application_StartUp you would have the following code
private void Application_Startup(object sender, StartupEventArgs e)
{
this.RootVisual = new MainPage();
if (e.InitParams.ContainsKey("usrIdentity"))
{
//I have a public static string WindowsUser on my MainPage.xaml.cs
MainPage.WindowsUser = e.InitParams["usrIdentity"];
}
}
This is from hewstone's suggestion. The MS link is http://msdn.microsoft.com/en-us/library/cc189004(v=vs.95).aspx

Correction to #Vishnoo Rath; you should try this:
<param name="initParams"
value="usrIdentity=<%=HttpContext.Current.User.Identity.Name%>"/>

Related

How do I implement IActivationForViewFetcher for a child UserControl?

I've just added ReactiveUI to an existing code base. Of course, for the first control I tried it with I hit a snag. I'm using it with a UserControl embedded in a TabControl. The code looks something like this:
public partial class TabPageControl : UserControl, IViewFor<TestViewModel>
{
public TabPageControl()
{
InitializeComponent();
ViewModel = new TestViewModel();
this.WhenActivated(dispose =>
{
dispose(this.Bind( ... ));
dispose(this.BindCommand( ... ));
});
}
}
When I run the app, I get the following error message:
Don't know how to detect when TabPageControl
is activated/deactivated, you may need to implement
IActivationForViewFetcher
So, how do I implement IActivationForViewFetcher? I'm not sure what I'm supposed to do with GetAffinityForView. I'm assuming in GetActivationForView I need to check to see if the UserControl is the currently visible inside the TabControl?
Although I would like to understand how to implement the methods for IActivationForViewFetcher (especially the part where I identify that a control is in the VisualTree) - the real cause of my problem was that my main assembly didn't have the appropriate references (the controls are in a class assembly).
I'm assuming (because I've skimmed the ReactiveUI source) ReactiveUI.Winforms.Registrations needs to be instantiated by the main assembly - which includes registering ActivationForViewFetcher.
Incidentally, the class library is written in C# and the main assembly is VB.NET. So I'm not sure whether this contributed to the problem.
At least it's working now!
I don't if this will ever help anybody, since this thread is so old.
What solved my issue was having ReactiveUI.WPF,ReactiveUI.WinForms, CefSharp.WPF and CefSharp.WinForms NuGet references on all the projects/plugins that were running on the App.
My suspicion is that when ReactiveUI/CefSharp is initialized and it doesn't contain all the info/files it needs, it will not possible to add them later on runtime. But this is just guessing based on my experience.
I know it's an old thread, but just to save other developers time when facing this problem.
My solution was to add the following code in the entrypoint of the project that makes use of ReactiveUi and ReactiveUi.Wpf.
var reactiveUiWpfName = typeof(ReactiveUI.Wpf.Registrations).Assembly.FullName;
Assembly.Load(reactiveUiWpfName);
Of course, it was just required because I couldn't reference ReactiveUi or ReactiveUi.Wpf in my application startup project due to the project specifications, otherwise this error wouldn't appear anyway.
(Please, observe that, in your case you should use ReactiveUi.Winforms in the places I've used ReactiveUi.Wpf)

How to get all the AutomationIDs of a WPF application in a file?

In automation of a WPF application (using UI Automation; VSTS 2010), we were adding all the Automation IDs in a Resource File manually and then access it one by one. Considering the application can expand any time, manually adding these IDs can become tedious.
So, is there any tool available which can create this for us? i.e. Get all the ids in a hierarchical format and store it in a file (xml or csv), and then we could parse it whenever required.
I was hoping for a tool like UISpy, which not only can spy all the elements but also export the same.
Do such tools exist? Or is there any alternate approach?
Any valuable feedback is highly appreciated.
Thanks!
I do like this:
public static class AutomationIds
{
public static readonly string MyDataGridId= Create();
private static string Create([CallerMemberName] string name = null)
{
return name;
}
}
<DataGrid AutomationProperties.AutomationId="{x:Static local:AutomationIds.MyDataGridId}"
... />
Then in tests
var dataGrid = window.Get<ListView>(AutomationIds.MyDataGridId);
Assign the automation IDs directly in XAML, then parse XAML files since they are XML after all...
Let's see...
First, I think that your data is not hierarchical - just because a control can be dynamically assigned to be a child of another.
If we change the problem to a subset: "how can we get a hierarchical view of the controls at a time t?" then we can answer this with MS UIA, and say, using a simple RawViewWalker (just a simple breadth-first search on the walker, starting from your main window will do - of course while the application is running so that UIA can reach and query it).
But this subset will not satisfy your initial question, because you'll probably see a portion of your whole ui collection (since some will be hidden / not activated yet at time t).
So it becomes very hard to use a UIA based tool (such as uispy) because then you'll have to set the application view to different states to reach all the controls in your application at different times t1, t2...
I would suggest parsing all your xmls at the same time and build a complete tree of the application's "static" control map, which I believe would be closest to what you're asking for.
Given that this is an old question, I doubt it matters anymore, but just wanted to make the distinctions here.

Sharepoint's Client Object Model with Silverlight, is it possible to load web.Language with executeQuery?

Is this:
Web web = context.Web;
context.Load(web, w => w.Language);
context.ExecuteQuery();
or something similar in order to load web.Language with context.ExecuteQuery() possible in a silverlight client? The above code was taken from
http://www.dev4side.com/community/blog/2011/1/5/incorrect-dates-taken-from-sharepoint-2010-client-object-model.aspx
When I do so, instantiating the web's Language property always yields
Microsoft.SharePoint.Client.PropertyOrFieldNotInitializedException
Btw, this code is in an extra thread (not the UI thread). I know that there is context.loadQueryAsync() but I already have an extra thread and would like to keep things together.
As far as I've tried this code works ok. Do you maybe access some other properties of the Web object that are not loaded? You'd have to include them also in your load method.

MEF & Silverlight: How do I navigate to a page in another XAP?

I'm very lost on how to do this.
I understand MEF and can load services and classes from another XAP using the ubiquitous DeploymentCatalogService found in many blog posts. What I don't understand is how to actually load and navigate to a PAGE from another XAP.
What I'd like to do is have my main application be able to call the NavigationService and provide it with the name of a Page that should exist. Like:
NavigationService.Navigate(new Uri("/Test", UriKind.Relative));
It's up to one of the other XAP files to provide this page to the application. However, I have no idea how to make this work. It seems like everyone is building up some complicated infrastructure to handle this situation and it's very annoying and overly complicated.
Is there an easy way to do this?
Some of the examples I've seen are more complicated than they need to be, but this is not a simple task. It took me 2 days to break down the examples I could find before I really understood what is going on.
To do this you need to create minimum two classes.
A class that implements INavigationContentLoader, this will do all of the work.
A class that implements IAsyncResult. This object will passed around the INavigationContentLoader, so use it to keep track of what you are doing.
Your INavgiationContentLoader should do the following.
BeginLoad
Test if the Uri belongs to the current XAP or a XAP that has already been loaded.
If not, use DeploymentCatalog to download the XAP. Store the DeploymentCatalog in an AggregateCatalog.
Create the page for the given Uri using an ExportFactory. Give yourself a property on your IAsyncResult to hold this.
If the operation has not been cancelled, execute the callback parameter.
CanLoad
You can try to put some logic in here to test of you have access to the specified XAP, or you can just return true and be done with it.
CancelLoad
Set a state within the IAsyncResult to let you know the operation has been cancelled.
EndLoad
Get the page that was stored in the IAsyncResult, wrap it in a LoadResult and return.
All pages that will be loaded by this INavgiationContentLoader will need to be marked with an ExportAttribute so that ExportFactory can find them.
Edit
My INavigationContentLoader
http://pastebin.com/cT1mJ4Ve
My IAsyncResult
http://pastebin.com/xHWHT4pr
ExportAttribute to use on pages. You need this on all pages, even the ones in the local XAP.
http://pastebin.com/nTJ27mWz
IExportPageMetaData. This is the contract that MEF uses.
http://pastebin.com/8fdwx2Kn
How to use:
Declare your navigation:Frame like this
<navigation:Frame x:Name="ContentFrame"
Source="/Home"`
Grid.Column="1">
<navigation:Frame.ContentLoader>
<navUtil:DynamicContentLoader />
</navigation:Frame.ContentLoader>
</navigation:Frame>
HyperlinkButton to a page from another XAP.
<HyperlinkButton Content="Page from another XAP"
NavigateUri="/NavigateUriFromExportPageAttribute"
navUtil:DynamicContentLoader.Xap="UriToOtherXap" />
HyperlinkButton to a page from this XAP.
<HyperlinkButton Content="Page from this XAP"
NavigateUri="/NavigateUriFromExportPageAttribute" />
You do not need a UriMapper, nor do you need to put the Path of the Page.xaml. MEF will read the ExportPageAttribute from the page and find the Uri that way.
Take a look to Navigating between Pages in Different Xaps (by using MEF) post on http://www.silverlightshow.net. It's exactly what you need. Source for post is also available.

MyGroups not implemented in Communicator.UIAutomation

I'm working on a out of browser Silverlight app that provides some MS Office Communicator 2007 controls. I'm using the Automation SDK. The docs that were installed with the SDK state that there's a MyGroups property in the IMessenger2 interface, which will return the groups that a user has defined, but when I try to use it, I get a NotImplementedException. Here's the code that I'm using:
dynamic communicator = AutomationFactory.CreateObject("Communicator.UIAutomation");
communicator.AutoSignin();
foreach (dynamic g in communicator.MyGroups)
{
//Do something with the group
}
If I replace MyGroups with MyContacts, I can get the contact list just fine. Do I have to do something different to access properties in the IMessenger2 interface? I've seen a few things on the web that say that MyGroups was deprecated for Windows Messenger, but from the docs, it seems like it should be available for MS Office Communicator.
If I can't use MyGroups, is there another way to get the groups that a user has created?
The problem here is that the MyGroups property is marked as NotScriptable, meaning you can't call it in the way you are doing i.e. using the AutomationFactory. For security reasons, some properties and methods in the Automation API are not scriptable - this is to avoid malicious pages automating Communicator and carrying out certain tasks without you knowing.
It looks like the COM interop in Silverlight is treated in the same way as e.g. creating and calling the API from VBScript, so you won't be able to access any of the non-scriptable properties and methods. See the reference for details of which properties and methods are not scriptable.
I'm guessing this is going to seriously hobble your app. I think what's hurting you is the decision to go with Silverlight OOB. Is there any way you could use WPF (or even winforms) rather than Silverlight? If you did this, you could reference the API directly, and have full access to all properties/methods.
Otherwise, I can't think of too many options. You can't trap the OnContactAddedToGroup event, as this is not scriptable.
It might be possible to wrap the API with a .NET assembly, and expose it via COM, then instantiate it in the same way - but the Not Scriptable might still be respected in that case, so it won't buy you anything. Hard to say without trying it, and still a fairly horrible solution.
Edit: I've just given the wrapper method a try (needed to do something similar as a proof of concept for a customer), and it seems to work. This is the way I did it:
Create a new .NET class library. Define a COM interface:
[ComVisible(true)]
[Guid("8999F93E-52F6-4E29-BA64-0ADC22A1FB11")]
public interface IComm
{
string GetMyGroups();
}
Define a class that implements that interface (you'll need to reference CommunicatorAPI.dll from the SDK):
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[GuidAttribute("C5C5A1A8-9BFB-4CE5-B42C-4E6688F6840B")]
[ProgId("Test.Comm.1")]
public class Comm : IComm
{
public string GetMyGroups()
{
var comm = new CommunicatorAPI.MessengerClass();
var groups = comm.MyGroups as IMessengerGroups;
return string.Join(", ", groups.OfType<IMessengerGroup>().Select(g => g.Name).ToArray());
}
}
Build, and register using RegAsm. Then call from the OOB silverlight app:
dynamic communicator = AutomationFactory.CreateObject("Test.Comm.1");
MessageBox.Show(communicator.GetMyGroups());
Note, the same technique also works using the Lync API:
public string GetMyGroups()
{
var comm = LyncClient.GetClient();
return string.Join(", ", comm.ContactManager.Groups.Select(g => g.Name).ToArray());
}
Although this works, I can't really say whether it's a good practice, as it's working around a security restriction which was presumably there for a good reason. I guess the worst that could happen is that a malicious web page could potentially use the component, if it knew the ProgId of the control.
Edit: Also, using this method you'd need to be careful about memory leaks, e.g. make sure you're releasing COM objects when you're finished with them - easy enough to do, just needs a little discipline ;o)

Resources