Silverlight - Getting the Domain Information - silverlight

How does a Silverlight application ask the browser what domain its being served up from?
UPDATE:
Make sure if your class doesn't already have this using statement add it at the top your class. This will help you on some of the examples you'll see online. It confused me for a bit.
using System.Windows.Browser;

How about HtmlDocument.DocumentUri? That'd get you what you need. Page about browser interop here.

As jcollum says you access the HtmlDocument.DocumentUri property to get lots of information on the host. To answer the question in your comment this is how you do this in Page.xaml.cs:
using System;
using System.Windows.Browser;
using System.Windows.Controls;
namespace SilverlightApplication1
{
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
string hostName = HtmlPage.Document.DocumentUri.Host;
int port = HtmlPage.Document.DocumentUri.Port;
}
}
}

Related

Rx Example not working

I'm trying to follow along with Jonathan Worthington's airport announcement example in An Event-driven and Reactive Future
It compiles.
The problem: SayGateChange is never called. I'm new to Rx. I must be leaving something out. What I have here is his code as exactly as I could transcribe it. Sadly, there is no source available online.
AddGateChange is supposed to push a new item onto EventStreams.GateChanged, which in turn is supposed to be watched by Announcer.Announcements, which is supposed to be watched by SayGateChange.
I'm in Windows forms, not WPF, if that makes a difference.
I will gladly put it into a console app or LinqPad if that will make it work.
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Reactive.Concurrency;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Threading;
public class frmAnnouncements
{
Announcer _Announcer = new Announcer();
ObservableCollection<string> Announcements = new ObservableCollection<string>();
private void frmRx_Load(System.Object sender, System.EventArgs e)
{
PopulateAnnouncements();
AddGateChange();
}
private void AddGateChange()
{
EventStreams.GateChanged.OnNext(new GateChanged {
Destination = "DAL",
FlightCode = 1503
});
}
private void PopulateAnnouncements()
{
_Announcer.Announcements.ObserveOnDispatcher().Subscribe(SayGateChange);
}
private void SayGateChange(string Message)
{
Interaction.MsgBox(Message);
}
public class GateChanged
{
public string FlightCode;
public string Destination;
}
public class EventStreams
{
public static Subject<GateChanged> GateChanged = new Subject<GateChanged>();
}
public class Announcer
{
public Announcer()
{
this.Announcements = EventStreams.GateChanged.Select(e => string.Format("gate change {0} to {1} ", e.FlightCode, e.Destination));
}
public IObservable<string> Announcements;
}
public frmAnnouncements()
{
Load += frmRx_Load;
}
}
As #Enigmativity stated, using ObserveOnDispatcher() is a problem - although without looking at Interaction.MsgBox its hard to be 100% certain it's the whole story - I guess it may be in the video, but it's rather long and I didn't watch it all.
The use of ObservableOnDispatcher() suggests you have pulled in the wrong nuget package for Rx:
For WPF applications, use rx-xaml (deprecated synonym rx-wpf), which provides the extension method ObserveOnDispatcher()
For Winforms applications, use rx-winforms, which provides the extension method overload ObserveOn(Control)
Both Winforms and WPF have a similar design where the user interface runs on a dedicated thread. In Winforms this is known as the "UI Thread" and in WPF as the "Dispatcher". Although the concept is very similar, the implementation is quite different.
ObserveOnDispatcher in WPF will cause the observer notifications OnXXX to be invoked on the dispatcher thread.
In WinForms, where you use ObserveOn(this), the this will generally be the form itself. For any WinForms control, this will locate the control's SynchronizationContext and Post OnXXX notifications to that.
Both overloads are smart in that invocations are direct if you happen to be on the correct Dispatcher thread or UI thread already.
I do seem to remember that WinForms is a lot more tolerant of updating UI off the UI thread - although this problem occurs in WPF too. This isn't a good thing, since it can lead to unpredictable results that are hard to debug. I note that the WinForms MessageBox.Show method, for example, doesn't care which thread it is invoked on since it creates it's own window. In general, use of some form of ObserveOn/ObserveOnDispatcher is always recommended in UI scenarios.
For this reason, it's a good idea to understand how these work in detail. For this, and to learn about the related SubscribeOn, have a look at this question.
I am surprised that you didn't get an informative InvalidOperationException stating that "The current thread has no Dispatcher associated with it." I can only think some other part of your code is swallowing exceptions, or you are using WPF code in your app as well and a Dispatcher had been created associated with the Winforms UI thread. That code behind Interaction.MsgBox is probably to blame for swallowing an error. Either way, I suggest removing rx-xaml to avoid confusion.

Serializing anonymous types in Silverlight with json.net

I'm having some problems serializing an anonymous type only on the Silverlight platform. I have code on .net 4.0 and .netcf that works fine.
This line right here
Newtonsoft.Json.JsonConvert.SerializeObject(new { Something = "yup" });
throws an aptly named guy, JsonSerializationException:
Error getting value from 'Something' on '<>f__AnonymousType0`1[System.String]'.
I tried 4.0r1 and 4.0r2 - Am I doing something wrong or am I taking crazy pills?
The problem is that anonymous types are defined as internal classes by the compiler. JSON.NET relies on reflection to work, and in Silverlight reflection across assembly borders work only for public types (when used by partially trusted assemblies such as this one).
I think DataContractJsonSerializer as mentioned in the previous answer is the way to go in this case, since it's part of the framework and should have extra privileges.
Another thing to try is use dictionaries or ExpandoObject's instead of anonymous types, but YMMV.
Answer is simple;) Add [assembly: InternalsVisibleTo("Newtonsoft.Json")] to AssemblyInfo.cs and voila... I have exactly the same problem and this attribute solved my serialization/deserialization problem.
AssemblyInfo.cs
[assembly: InternalsVisibleTo("Newtonsoft.Json")]
Is there a specific reason why you want to use Json.NET? If not, you might want to try the built-in serializer (in the System.Runtime.Serialization namespace). I have to admit, I have never tried it with anonymous types, so I am not sure if this will be useful to you. Anyway, here is the class I use for serialization/deserialization:
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
using System.Text;
using System.Runtime.Serialization.Json;
namespace GLS.Gui.Helper
{
public static class SerializationHelper
{
public static string SerializeToJsonString(object objectToSerialize)
{
using (MemoryStream ms = new MemoryStream())
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(objectToSerialize.GetType());
serializer.WriteObject(ms, objectToSerialize);
ms.Position = 0;
using (StreamReader reader = new StreamReader(ms))
{
return reader.ReadToEnd();
}
}
}
public static T Deserialize<T>(string jsonString)
{
using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString)))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
return (T)serializer.ReadObject(ms);
}
}
}
}
Maybe have a look at this http://whydoidoit.com/silverlight-serializer/ as I have used this to serialize many objects in Silverlight, although I cant remember if i did anonymous types with it.
To supplement the other answers with another workaround, note that the reflection (and so the serialization of anonymous types) will succeed when running with elevated trust.

Caliburn.Micro + MEF + SQL CE together produce exception Cannot open 'Db\Some.sdf'. Provider 'System.Data.SqlServerCe.3.5' not installed

Hi I am really confuse with this behavior. I use Caliburn.Micro as MVVM framework in my WPF app, MEF is used on export view models classes.
Now I need use SQL compact DB in my app. So I create *dbml file with sqlmetal, because on DB access I would like to use LINQ TO SQL.
First I create simple class which do CRUD operations DB.
Here is it:
public interface IDbManager{}
[Export(typeof(IDbManager))]
public class DbManager : IDbManager
{
//_dc is DataContext class
private Spiri_SQL_CE_DB _dc;
public DbManager()
{
//string connStr = System.Configuration.ConfigurationManager.AppSettings["connstr"];
//_dc = new Spiri_SQL_CE_DB(connStr);
_dc = new Spiri_SQL_CE_DB(#"Db\Spiri_SQL_CE_DB.sdf");
}
}
This class is used in view model class which is WPF window.
[Export(typeof(IArchiveViewModel))]
public class ArchiveViewModel :Screen,IArchiveViewModel
{
private IDbManager _dbManager;
[ImportingConstructor]
public ArchiveViewModel(IDbManager dbManager)
{
_dbManager = dbManager;
}
}
And this window I open from screen with WindowManager class.
[Export(typeof(IMessengerViewModel))]
public class MessengerViewModel : Screen, IMessengerViewModel
{
private IWindowManager _windowManager;
[ImportingConstructor]
public MessengerViewModel(IWindowManager windowManager)
{
_windowManager = windowManager;
OpenArchive();
}
public void OpenArchive()
{
var w = IoC.Get<IArchiveViewModel>();
_windowManager.ShowWindow(w);
}
If I run app I get this error:
The composition produced a single composition error. The root cause is provided below. Review the CompositionException.Errors property for more detailed information.
1) Cannot open 'Db\Spiri_SQL_CE_DB.sdf'. Provider 'System.Data.SqlServerCe.3.5' not installed.
Resulting in: An exception occurred while trying to create an instance of type 'Spirit.DbManager.DbManager'.
Resulting in: Cannot activate part 'Spirit.DbManager.DbManager'.
Element: Spirit.DbManager.DbManager --> Spirit.DbManager.DbManager --> AssemblyCatalog (Assembly="Spirit, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
Resulting in: Cannot get export 'Spirit.DbManager.DbManager (ContractName="Spirit.DbManager.IDbManager")' from part 'Spirit.DbManager.DbManager'.
Element: Spirit.DbManager.DbManager (ContractName="Spirit.DbManager.IDbManager") --> Spirit.DbManager.DbManager --> AssemblyCatalog (Assembly="Spirit, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
}
I am really confuse with this error:
1) Cannot open 'Db\Spiri_SQL_CE_DB.sdf'. Provider 'System.Data.SqlServerCe.3.5' not installed.
Beacause:
I use Window 7 x64, I have installed SQL Server CE for .NET4.0, .NET3.5
WPF use .NET4.0 and is x86
In WPF I have reference on assembly system.data.sqlserverce.dll
I create small repo project but I get same error:
Repo project you can find here: http://netload.in/dateiy4s4jdPyCj/DbTest.7z.htm
I think problem code is here:
_dc = new Spiri_SQL_CE_DB(#"Db\Spiri_SQL_CE_DB.sdf");
Spiri_SQL_CE_DB class is from *.dbml file.
I create view model class without MEF I get the same error!
So I try use DbManager class in WPF app without Calibur.Micro and MEF and it works good.
I really don’t know what is bad, I search with google 2 hours but any advice don’t solve this error.
If anybody can help I would be very glad.
Reinstall the 3.5 SP2 MSI, and if you have a x64 system, install both the x86 and x64 MSIs: http://www.microsoft.com/downloads/en/details.aspx?familyid=E497988A-C93A-404C-B161-3A0B323DCE24&displaylang=en

Issue intercepting property in Silverlight application

I am using Ninject as DI container in a Silverlight application. Now I am extending the application to support interception and started integrating DynamicProxy2 extension for Ninject. I am trying to intercept call to properties on a ViewModel and ending up getting following exception:
“Attempt to access the method failed: System.Reflection.Emit.DynamicMethod..ctor(System.String, System.Type, System.Type[], System.Reflection.Module, Boolean)”
This exception is thrown when invocation.Proceed() method is called. I tried two implementations of the interceptor and they both fail
public class NotifyPropertyChangedInterceptor: SimpleInterceptor
{
protected override void AfterInvoke(IInvocation invocation)
{
var model = (IAutoNotifyPropertyChanged)invocation.Request.Proxy;
model.OnPropertyChanged(invocation.Request.Method.Name.Substring("set_".Length));
}
}
public class NotifyPropertyChangedInterceptor: IInterceptor
{
public void Intercept(IInvocation invocation)
{
invocation.Proceed();
var model = (IAutoNotifyPropertyChanged)invocation.Request.Proxy;
model.OnPropertyChanged(invocation.Request.Method.Name.Substring("set_".Length));
}
}
I want to call OnPropertyChanged method on the ViewModel when property value is set.
I am using Attribute based interception.
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class NotifyPropertyChangedAttribute : InterceptAttribute
{
public override IInterceptor CreateInterceptor(IProxyRequest request)
{
if(request.Method.Name.StartsWith("set_"))
return request.Context.Kernel.Get<NotifyPropertyChangedInterceptor>();
return null;
}
}
I tested the implementation with a Console Application and it works alright.
I also noted in Console Application as long as I had Ninject.Extensions.Interception.DynamicProxy2.dll in same folder as Ninject.dll I did not have to explicitly load DynamicProxy2Module into the Kernel, where as I had to explicitly load it for Silverlight application as follows:
IKernel kernel = new StandardKernel(new DIModules(), new DynamicProxy2Module());
Could someone please help? Thanks
Reflection can be really tricky in silverlight because of security issues.
Check Gabe's answer for this question, it's the same problem.
The good news is that you can achieve the same functionality you want using dynamic instead of proxies. Just extend your ViewModel from DynamicObject and override the TrySetMember method.
I hope it helps :)

Silverlight Async Timeout Error

Calling through to my Silverlight Enabled WCF-Service in my silverlight application, occasionally users get timeouts. Whats the easiest way to boost the time allowed by the service client for a response?
The exact exception thrown is: System.TimeoutException: [HttpRequestTimedOutWithoutDetail]
Thanks
Ammount of time connection can be open: BasicHttpBinding.OpenTimeout property
Time that a connection can remain inactive, during which no application messages are received, before it is dropped: BasicHttpBinding.ReceiveTimout property
This can be set in the node of the ServiceReference.ClientConfig file in the silverlight app.
The accepted answer here did not work for me. Instead I had to cast the base channel into an IContextChannel, and set the OperationTimeout on that.
To do that, I had to create a new file with a partial class, that matched the name of the ServiceReference. In my case the I had a PrintReportsService. Code is below.
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace RecipeManager.PrintReportsService
{
public partial class PrintReportsClient : System.ServiceModel.ClientBase<RecipeManager.PrintReportsService.PrintReports>, RecipeManager.PrintReportsService.PrintReports
{
public void SetOperationTimeout(TimeSpan timeout)
{
((System.ServiceModel.IContextChannel)base.Channel).OperationTimeout = timeout;
}
}
}
Then when I create the client, I do the following:
PrintReportsService.PrintReportsClient client = new RecipeManager.PrintReportsService.PrintReportsClient();
client.SetOperationTimeout(new TimeSpan(0, 4, 0));
That did it for me! More info is available here, but the code snippet in this post doesn't compile.
This can be set, but there is an upper limit that is defined by the underlying HTTP library (I think its five minutes). Note that using a higher value will fall back to what the upper limit is. Also, be aware that you may need to configure the timeout on the server as well.
I fixed this by enabling compatibility mode in IE
Rather than changing the timeout, I think you should implement a timer-based callback to the server from the Silverlight application so that the session doesn't expire. This would eliminate the overhead of longer timeouts for all of your application.

Resources