I'm using SignalR in my server side code c# .net4.
On client I'm using javascript.
when I Invoke client method from server ,for example
Caller.ShowDate(DateTime.Now);
client side javascript gets value of "2012-11-13T19:02:39.3386544+02:00" as string.
How can I use It as Date in javascript ?
Keep in mind that client times can be VASTLY different than server times due to time zones/clients modifying clocks etc. That being said:
C#:
Caller.ShowDate(DateTime.UtcNow);
JavaScript:
myHub.client.ShowDate = function(d) {
var serverTime = new Date(d); // The Server Time in JavaScript
}
If you unhappy man which use IE8 then can read comment below:
SignalR uses Json.Net-library to (de)serialize data.
Before .NET 4.5 Json.NET used epoch-format ("/Date(1198908717056)/") and then began to be used ISO8601 standard ("2012-03-19T07:22Z") [see Serializing Dates in JSON].
If you want to use epoch-format you need to reconfigure json-serializator [see Replacing the IJsonSerializer]:
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
var serializer = new JsonNetSerializer(new JsonSerializerSettings
{
DateFormatHandling = DateFormatHandling.MicrosoftDateFormat,
NullValueHandling = NullValueHandling.Ignore
});
GlobalHost.DependencyResolver.Register(typeof(IJsonSerializer), () => serializer);
}
}
On client side you can use this code to convert epoch-time to Date:
function epochUtcToDate(epochUtc) {
return new Date(parseInt(epochUtc.substr(6), 10));
};
If you have add time zone to Json date you need use local time from server
public class Startup
{
public void Configuration(IAppBuilder app)
{
GlobalHost.HubPipeline.AddModule(new ElmahPipelineModule());
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
};
map.RunSignalR(hubConfiguration);
});
var jsonSerializer = new JsonSerializer();
jsonSerializer.DateFormatHandling = DateFormatHandling.IsoDateFormat;
jsonSerializer.DateTimeZoneHandling = DateTimeZoneHandling.Local;
jsonSerializer.NullValueHandling = NullValueHandling.Ignore;
GlobalHost.DependencyResolver.Register(typeof(JsonSerializer), () => jsonSerializer);
}
}
Related
I have a problem with accessing values in the session through pagemethods when I try connecting to SQL Server.
I have uploadEngin.aspx page for uploading files and for monitoring the upload state I store the state value (like 10%) in session. In the uploadEngin.aspx page I am connecting to SQL Server to get the valid extension for files. I have a basic problem. Example below show a sample code:
uploadEngin:
protected void Page_Load(object sender, EventArgs e)
{
this.Session["s"] = "hello";
if (!IsPostBack)
{
admin.app.core.attachment.AttachmentType att = new app.core.attachment.AttachmentType();
att.GetExtentionAndMainPath("Image");
}
}
[System.Web.Services.WebMethod(EnableSession = true)]
public static String g()
{
return HttpContext.Current.Session["s"].ToString();
}
Javascript:
(function () {
window.onload = function () {
PageMethods.g(function (r) { alert(r); }, function (r) {
console.log(r);
});
}
})();
GetExtentionAndMainPath:
public String[] GetExtentionAndMainPath(String name)
{
String[] ext =new String[2];
String x = name;
UInt64 id = FindIdByName(x);
DataTable dt = new DataAccess().ExecuteSelect("Select_ano_attachmentType", CommandType.StoredProcedure, new DataParam("#id", id, SqlDbType.BigInt));
if (dt.Rows.Count > 0)
{
ext[0] = dt.Rows[0]["attachmentType_validExtention"].ToString();
ext[1]= dt.Rows[0]["attachmentType_mainPath"].ToString();
}
return ext;
}
Without code inside if(!isPostBack) everything works fine and I see the "hello" message. When I use that code however (connecting to SQL Server to get the valid extension), I get
WebServiceError: Object reference not set to an instance of an object
How should I solve this problem?
You need to set EnableSession property on your WebMethod attribute in order to access Session values in your web method.
[WebMethod(EnableSession = true)]
public static String g()
{
return HttpContext.Current.Session["s"].ToString();
}
For more details, please refer the MSDN link.
I have been "too" succesfully with my stand-alone Singular web service. We would like to now remove the IIS server, which does little other than serve about 10 JS/HTML/CSS files. Node.JS has a static-files plugin,
I looked and I saw that Katana, OWIN.SelfHost also has such a feature.
http://odetocode.com/blogs/scott/archive/2014/02/10/building-a-simple-file-server-with-owin-and-katana.aspx
Update
It was suggested to use the OWIN.Self-Host which has a feature, but I am unsure of where to put it in my existing code, and if it would effect the existing SIGNALR code (all Hubs share the same HTTP request calls, so I am also squeezing in Self-host on the same port, I wonder if that works). As well as it would be nice to use Scott Allen's (above referenced) example which also allows File Browsing.
Here is the code I current use to start up SIGNALR (V2.2) , which is run at the directly from the Main.cs file:
class Comm
{
public string url = "http://localhost:7700";
// string url = "http://*:7700"; // Requires admin privileges
public void start()
{
Task t = Task.Run(() =>
{
WebApp.Start<Startup>(url);
this.Clients = GlobalHost.ConnectionManager.GetHubContext<GatewayHub>().Clients;
Console.WriteLine("Server running on {0}", url);
Thread.Sleep(Timeout.Infinite);
});
}
public void send()
{
Clients.All.display("broadcast sent...");
}
private IHubConnectionContext<dynamic> Clients
{
get;
set;
}
}
class Startup
{
public void Configuration(IAppBuilder app)
{
var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = (Tools.LogLevel >= 12);
hubConfiguration.EnableJavaScriptProxies = true;
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR("/signalr", hubConfiguration);
}
}
This answer is really from #Tracther, and I wish he would write it up so that I can credit him. But thanks to his input, here is what works for me. I did not need the commented lines. All I needed was to set the paths for /signlar and for the static FileSystem
}
class Startup
{
public void Configuration(IAppBuilder app)
{
var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = (Tools.DebugLevel > 12);
hubConfiguration.EnableJavaScriptProxies = true;
app.UseCors(CorsOptions.AllowAll);
//app.UseStaticFiles();
app.UseFileServer(new FileServerOptions()
{
//RequestPath = new PathString("/Scopes"),
EnableDirectoryBrowsing = true,
FileSystem = new PhysicalFileSystem(#".\Scopes"),
});
app.MapSignalR("/signalr", hubConfiguration);
}
}
I created a server hub in an asp.net application like below
public class Calc : Hub
{
public void CalculateSomething(int a, int b)
{
// start working in a new thread
var task = Task.Factory.StartNew(() => DoCalculate(a, b));
// attach a continuation task to notify
// the client when the work is done
task.ContinueWith(t =>
{
System.Threading.Thread.Sleep(2000);
Clients.addMessage(t.Result);
Caller.notifyCalculateResult(t.Result);
System.Threading.Thread.Sleep(2000);
Caller.notifyCalculateResult("Completed");
Clients.addMessage("Completed");
});
}
private int DoCalculate(int p1, int p2)
{
// do some slow work on the input,
// e.g. call webservice or I/O.
int result = p1 + p2;
//int result = DoSlowWork(p1, p2);
return result;
}
}
Now in another asp.net application I created a client using SiganlR client. But it's not working correctly. I am looking to get data from server as it pushes to client
using System.Threading.Tasks;
using SignalR;
using SignalR.Client;
using SignalR.Client.Hubs;
namespace WebApplication2
{
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
// Connect to the service
var hubConnection = new HubConnection("http://localhost:3119/");
// Create a proxy to the chat service
var chat = hubConnection.CreateProxy("Calc");
// Print the message when it comes in
chat.On("addMessage", message =>Print(message));
// Start the connection
hubConnection.Start().Wait();
// Send a message to the server
chat.Invoke("CalculateSomething", 1, 2).Wait();
}
private async void Print(object message)
{
Response.Write(message);
}
}
}
The console client application works fine. The main problem is with asp.net beacause it fails to the handle call back from server.
Looks like you calling the server side method wrongly, try this
chat.Invoke("CalculateSomething", 1, 2).ContinueWith(task =>
{
Console.WriteLine("Value from server {0}", task.Result);
});
a small but very annoying problem. I am trying to use jQuery JSON call with asp.net web service. It all works fine with the below HttpModule if I call the web service without any arguments. As soon as I try and send a value from the client side, Module gets executed but the process doesn't pass over to the actual webservice method and returns with a server side 500 error. If we remove the module from the middle, then the method gets executed perfectly fine with parameter but then the response comes back in the XML format instead of JSON so we are helpless to use the Module.
----------- Jquery Call ---------------------
var dd = { 'name': 'pakistan' };
$(document).ready(function () {
$.getJSON("http://localhost:59271/Testing/shows-app.asmx/HelloWorld?callback=?",
dd,
function (data) {
val = JSON.parse(data.d)
$("#content").html(val.response);
});
});
------------ HttpModule -------------
private const string JSON_CONTENT_TYPE = "application/json; charset=utf-8";
public void Dispose()
{
}
public void Init(HttpApplication app)
{
app.BeginRequest += OnBeginRequest;
app.EndRequest += new EventHandler(OnEndRequest);
}
public void OnBeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpRequest request = app.Request;
//Make sure we only apply to our Web Service
if (request.Url.AbsolutePath.ToLower().Contains("-app."))
{
var method = app.Context.Request.Headers["REQUEST_METHOD"];
if (string.IsNullOrEmpty(app.Context.Request.ContentType))
{
app.Context.Request.ContentType = JSON_CONTENT_TYPE;
}
app.Context.Response.Write(app.Context.Request.Params["callback"] + "(");
var method2 = app.Context.Request.Headers["REQUEST_METHOD"];
}
}
void OnEndRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpRequest request = app.Request;
if (request.Url.AbsolutePath.ToLower().Contains("-app."))
{
app.Context.Response.Write(")");
app.Context.Response.ContentType = "application/json";
}
}
----------- Webservice ---------------------
[WebMethod]
[System.Web.Script.Services.ScriptMethod(UseHttpGet = true, ResponseFormat = System.Web.Script.Services.ResponseFormat.Json)]
public string HelloWorld(string name)
{
var json = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(new
{
response = "Pakistan " + " Zindabad"
});
return json;
//string jsoncallback = HttpContext.Current.Request["callback"];
//return string.Format("{0}({1})", jsoncallback, json);
}
Please remember that, if we remove the module from the middle, then the method gets executed perfectly fine with parameter but then the response comes back in the XML format instead of JSON so we are helpless to use the Module.
Thanks a bunch in advance.
I have been experimenting with WP7 apps today and have hit a bit of a wall.
I like to have seperation between the UI and the main app code but Ive hit a wall.
I have succesfully implemented a webclient request and gotten a result, but because the call is async I dont know how to pass this backup to the UI level. I cannot seem to hack in a wait for response to complete or anything.
I must be doing something wrong.
(this is the xbox360Voice library that I have for download on my website: http://www.jamesstuddart.co.uk/Projects/ASP.Net/Xbox_Feeds/ which I am porting to WP7 as a test)
here is the backend code snippet:
internal const string BaseUrlFormat = "http://www.360voice.com/api/gamertag-profile.asp?tag={0}";
internal static string ResponseXml { get; set; }
internal static WebClient Client = new WebClient();
public static XboxGamer? GetGamer(string gamerTag)
{
var url = string.Format(BaseUrlFormat, gamerTag);
var response = GetResponse(url, null, null);
return SerializeResponse(response);
}
internal static XboxGamer? SerializeResponse(string response)
{
if (string.IsNullOrEmpty(response))
{
return null;
}
var tempGamer = new XboxGamer();
var gamer = (XboxGamer)SerializationMethods.Deserialize(tempGamer, response);
return gamer;
}
internal static string GetResponse(string url, string userName, string password)
{
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
{
Client.Credentials = new NetworkCredential(userName, password);
}
try
{
Client.DownloadStringCompleted += ClientDownloadStringCompleted;
Client.DownloadStringAsync(new Uri(url));
return ResponseXml;
}
catch (Exception ex)
{
return null;
}
}
internal static void ClientDownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
ResponseXml = e.Result;
}
}
and this is the front end code:
public void GetGamerDetails()
{
var xboxManager = XboxFactory.GetXboxManager("DarkV1p3r");
var xboxGamer = xboxManager.GetGamer();
if (xboxGamer.HasValue)
{
var profile = xboxGamer.Value.Profile[0];
imgAvatar.Source = new BitmapImage(new Uri(profile.ProfilePictureMiniUrl));
txtUserName.Text = profile.GamerTag;
txtGamerScore.Text = int.Parse(profile.GamerScore).ToString("G 0,000");
txtZone.Text = profile.PlayerZone;
}
else
{
txtUserName.Text = "Failed to load data";
}
}
Now I understand I need to place something in ClientDownloadStringCompleted but I am unsure what.
The problem you have is that as soon as an asynchronous operation is introduced in to the code path the entire code path needs to become asynchronous.
Because GetResponse calls DownloadStringAsync it must become asynchronous, it can't return a string, it can only do that on a callback
Because GetGamer calls GetResponse which is now asynchronous it can't return a XboxGamer, it can only do that on a callback
Because GetGamerDetails calls GetGamer which is now asynchronous it can't continue with its code following the call, it can only do that after it has received a call back from GetGamer.
Because GetGamerDetails is now asynchronous anything call it must also acknowledge this behaviour.
.... this continues all the way up to the top of the chain where a user event will have occured.
Here is some air code that knocks some asynchronicity in to the code.
public static void GetGamer(string gamerTag, Action<XboxGamer?> completed)
{
var url = string.Format(BaseUrlFormat, gamerTag);
var response = GetResponse(url, null, null, (response) =>
{
completed(SerializeResponse(response));
});
}
internal static string GetResponse(string url, string userName, string password, Action<string> completed)
{
WebClient client = new WebClient();
if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
{
client.Credentials = new NetworkCredential(userName, password);
}
try
{
client.DownloadStringCompleted += (s, args) =>
{
// Messy error handling needed here, out of scope
completed(args.Result);
};
client.DownloadStringAsync(new Uri(url));
}
catch
{
completed(null);
}
}
public void GetGamerDetails()
{
var xboxManager = XboxFactory.GetXboxManager("DarkV1p3r");
xboxManager.GetGamer( (xboxGamer) =>
{
// Need to move to the main UI thread.
Dispatcher.BeginInvoke(new Action<XboxGamer?>(DisplayGamerDetails), xboxGamer);
});
}
void DisplayGamerDetails(XboxGamer? xboxGamer)
{
if (xboxGamer.HasValue)
{
var profile = xboxGamer.Value.Profile[0];
imgAvatar.Source = new BitmapImage(new Uri(profile.ProfilePictureMiniUrl));
txtUserName.Text = profile.GamerTag;
txtGamerScore.Text = int.Parse(profile.GamerScore).ToString("G 0,000");
txtZone.Text = profile.PlayerZone;
}
else
{
txtUserName.Text = "Failed to load data";
}
}
As you can see async programming can get realy messy.
You generally have 2 options. Either you expose your backend code as an async API as well, or you need to wait for the call to complete in GetResponse.
Doing it the async way would mean starting the process one place, then return, and have the UI update when data is available. This is generally the preferred way, since calling a blocking method on the UI thread will make your app seem unresponsive as long as the method is running.
I think the "Silverlight Way" would be to use databinding. Your XboxGamer object should implement the INotifyPropertyChanged interface. When you call GetGamer() it returns immediately with an "empty" XboxGamer object (maybe with GamerTag=="Loading..." or something). In your ClientDownloadStringCompleted handler you should deserialize the returned XML and then fire the INotifyPropertyChanged.PropertyChanged event.
If you look at the "Windows Phone Databound Application" project template in the SDK, the ItemViewModel class is implemented this way.
Here is how you can expose asynchronous features to any type on WP7.