This is a migrated thread and some comments may be shown as answers.

Data from SignalR hub not visible in Grid

10 Answers 494 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Michael
Top achievements
Rank 1
Veteran
Iron
Michael asked on 21 Feb 2019, 11:24 AM

Hi!

I have a problem with SignalR and the Grid.

I have a hub like this:

01.public class ACTaskHub : Hub
02.{
03.    private IMemoryCache taskCache;
04. 
05.    public ACTaskHub(IMemoryCache cache)
06.    {
07.        taskCache = cache;
08.    }
09. 
10.    public override Task OnConnectedAsync()
11.    {
12.        //Groups.AddToGroupAsync(Context.ConnectionId, GetGroupName());
13.        return base.OnConnectedAsync();
14.    }
15. 
16.    public override Task OnDisconnectedAsync(Exception exception)
17.    {
18.        //Groups.RemoveFromGroupAsync(Context.ConnectionId, GetGroupName());
19.        return base.OnDisconnectedAsync(exception);
20.    }
21. 
22.    public IEnumerable<TaskViewModel> Read()
23.    {
24.        var tasks = taskCache.Get("tasks") as IEnumerable<TaskViewModel>;
25. 
26.        if (tasks == null)
27.        {
28.            var products = AppData.TaskList.Select(t => new TaskViewModel
29.            {
30.                ID = t.ID,
31.                Name = t.Name,
32.                LastRunTime = t.LastRunTime,
33.                Duration = t.Duration,
34.                Schedule = t.Schedule,
35.                Status = t.Status.ToString(),
36.                Result = t.LastResult,
37.                Exception = t.Exception?.Message,
38.                CreatedAt = DateTime.Now.AddMilliseconds(1)
39.            });
40.             
41.            tasks = products.ToList();
42.            taskCache.Set("tasks", tasks, TimeSpan.FromMinutes(30));
43.        }
44. 
45.        return tasks;
46.    }
47. 
48.    public TaskViewModel Create(TaskViewModel task)
49.    {
50.        //task.ID = Guid.NewGuid();
51.        //product.CreatedAt = DateTime.Now;
52.        //product.Category = product.Category ?? new CategorySignalR() { CategoryID = 1 };
53. 
54.        //Clients.OthersInGroup(GetGroupName()).SendAsync("create", task);
55.        Clients.Others.SendAsync("create", task);
56. 
57.        return task;
58.    }
59. 
60.    public void Update(TaskViewModel task)
61.    {
62.        //Clients.OthersInGroup(GetGroupName()).SendAsync("update", task);
63.        Clients.Others.SendAsync("update", task);
64.    }
65. 
66.    public void Destroy(TaskViewModel task)
67.    {
68.        //Clients.OthersInGroup(GetGroupName()).SendAsync("destroy", task);
69.        Clients.Others.SendAsync("destroy", task);
70.    }
71. 
72.    //public string GetGroupName()
73.    //{
74.    //    return GetRemoteIpAddress();
75.    //}
76. 
77.    //public string GetRemoteIpAddress()
78.    //{
79.    //    return Context.GetHttpContext()?.Connection.RemoteIpAddress.ToString();
80.    //}
81.}

 

And i use Kendo Grid with SignalR datasource to show the hub data like this:

@(Html.Kendo().Grid<TaskViewModel>()
    .Name("TaskList")
    .Columns(columns =>
    {
        columns.Bound(t => t.Name).Width(140);
        columns.Bound(t => t.LastRunTime).Format("{0:yyyy-MM-dd hh:mm:ss}").Width(150);
        columns.Bound(t => t.Duration).HtmlAttributes(new { style = "text-align:right" }).Width(130);
        columns.Bound(t => t.Schedule).Width(100);
        columns.Bound(t => t.Status).Width(80);
        columns.Bound(t => t.Result).Filterable(false).Width(250);
        columns.Bound(t => t.Exception).Filterable(false).Width(150);
    })
    .Sortable()
    .Scrollable()
    .Filterable()
    .Resizable(resize => resize.Columns(true))
    .HtmlAttributes(new { style = "maxheight:530px;" })
    .DataSource(dataSource => dataSource
        .SignalR()
        .AutoSync(true)
        .Events(events => events.Push("onPush"))
        .Events(events => events.Error("onError"))
        .Sort(s => s.Add("CreatedAt").Descending())
        .Transport(tr => tr
            .Promise("hubStart")
            .Hub("hub")
            .Client(c => c
                .Read("read")
                .Create("create")
                .Destroy("destroy")
                .Update("update"))
            .Server(s => s
                .Read("read")
                .Create("create")
                .Destroy("destroy")
                .Update("update")))
        .Schema(schema => schema
            .Model(model =>
            {
                model.Id("ID");
                model.Field("ID", typeof(string)).Editable(false);
                model.Field("CreatedAt", typeof(DateTime)).Editable(false);
                model.Field("Name", typeof(string)).Editable(false);
                model.Field("LastRunTime", typeof(DateTime)).Editable(false);
                model.Field("Duration", typeof(TimeSpan)).Editable(false);
                model.Field("Schedule", typeof(string)).Editable(false);
                model.Field("Status", typeof(string)).Editable(false);
                model.Field("Result", typeof(string)).Editable(false);
                model.Field("Exception", typeof(string)).Editable(false);
            })
        )
    )
)

 

The hub is connected and the data are loaded, but not visible in the grid. I can see the like of my task in the grid because of mouse hovering but the fields are empty. (see screenshot1.png)

 

The secound problem i have is, that when the data is updated from server the client want to invoke "create" method. Why is the client doing this?

I get this error message: (see screenshot2.png)

 

And why is the ASP.NET Core Grid SignalR demo not working: https://demos.telerik.com/aspnet-core/grid/signalr

 

 

 

 

 
 

10 Answers, 1 is accepted

Sort by
0
Michael
Top achievements
Rank 1
Veteran
Iron
answered on 21 Feb 2019, 02:15 PM
I think I found out something that could explain the first error (data will not be shown):
camelCase vs. PascalCase

When I look at the JSON data from the WebSocket Monitor, they are transferred to camelCase. The model at the grid is specified in PascalCase.

{"type":1,"target":"updateTask","arguments":[{"id":"d7c5c44f-03fa-401f-8b12-4f0ab3890b64","createdAt":"2019-02-21T15:06:27.8914385+01:00","name":"Hello World! Task","lastRunTime":"2019-02-21T15:03:26.5114048+01:00","duration":"00:00:06.3288123","schedule":"*/3 * * * *","status":"Running","result":"Hello World and hallo Mike!"}]}

It may then have something to do with the second error as a result.

Does Kendo Grid use camelCase or PascalCase?
 
 
0
Michael
Top achievements
Rank 1
Veteran
Iron
answered on 22 Feb 2019, 08:32 AM

Solution found: all the problems/failure were based on camelCase/PascalCase!

Check your ConfigureServices method in Startup.cs for the following:

01.services.AddMvc()
02.        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
03.        .AddJsonOptions(o =>
04.        {
05.            o.SerializerSettings.ContractResolver = new DefaultContractResolver();
06.            o.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
07.        });
08. 
09.services.AddSignalR(hubOptions => hubOptions.EnableDetailedErrors = true)
10.        .AddJsonProtocol(jsonOptions =>
11.        {
12.            jsonOptions.PayloadSerializerSettings.ContractResolver = new DefaultContractResolver();
13.            jsonOptions.PayloadSerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
14.        });

 

And check if you are using

[JsonProperty("name")]

in your models because this feature makes your Pascal Case attitude back to CamelCase.

That was my mistake!

 
 
0
Abdullah
Top achievements
Rank 1
answered on 24 Apr 2019, 08:28 AM
thank you. changing the services with :

services.AddSignalR(hubOptions => hubOptions.EnableDetailedErrors = true)
.AddJsonProtocol(jsonOptions =>
{
jsonOptions.PayloadSerializerSettings.ContractResolver = new DefaultContractResolver();
jsonOptions.PayloadSerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
});

worked like hell..
0
Alex Hajigeorgieva
Telerik team
answered on 29 Apr 2019, 06:33 AM
Hi, Michael,

The default serialization was changed by Microsoft in 2016 thus making it necessary to specify the the settings:

https://github.com/aspnet/Announcements/issues/194

We included this in our getting started article, step 5:

https://docs.telerik.com/aspnet-core/getting-started/getting-started

The serialization for SignalR should be part of the SignalR settings. Here is the link to the online project service startup file:

https://github.com/telerik/kendo-ui-demos-service/blob/master/signalr-hubs/signalr-for-aspnet-core/Startup.cs#L40

public void ConfigureServices(IServiceCollection services)
 {
      /* otherr services */
    services.AddSignalR()
        .AddJsonProtocol(x =>
            x.PayloadSerializerSettings.ContractResolver = new DefaultContractResolver());
}

Finally, you mentioned that the official SignalR ASP.NET Core demo does not work. Could you let us know what specifically  is not working so we can investigate?

Kind Regards,
Alex Hajigeorgieva
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Michael
Top achievements
Rank 1
Veteran
Iron
answered on 29 Apr 2019, 06:42 AM

Hi Alex,

thx for the reply!

I have checked the demo again, and now its working fine! (In those days, no data was loaded and displayed!)

0
Alex Hajigeorgieva
Telerik team
answered on 02 May 2019, 05:40 AM
Hello,Michael,

Maybe it was a brief disruption on the server where the service is.

It is great that it works fine now, thank you for getting in touch about it.

Kind Regards,
Alex Hajigeorgieva
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Don
Top achievements
Rank 1
answered on 23 Oct 2019, 09:02 PM

I just want to add to the answers... For applications using ASP.NET Core 3.0 framework, the codes to use is:

        public void ConfigureServices(IServiceCollection services)
        {
            // ** Other services such as AddMvc, AddNewtonsoftJson, AddKendo go here first **

            services.AddSignalR()
                .AddJsonProtocol(options =>
                {
                     options.PayloadSerializerOptions.PropertyNamingPolicy = null;
                });

        }

0
Alex Hajigeorgieva
Telerik team
answered on 24 Oct 2019, 08:18 AM

Hi, Don,

Thank you very much for updating the thread with your solution.

Kind Regards,
Alex Hajigeorgieva
Progress Telerik

Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Dayanand
Top achievements
Rank 1
answered on 25 Feb 2020, 04:42 PM

What is AppData while creating SignalR hub in above example.  I am getting

 

  var products = AppData.TaskList.Select(t => new TaskViewModel
29.            {
30.                ID = t.ID,
31.                Name = t.Name,
32.                LastRunTime = t.LastRunTime,
33.                Duration = t.Duration,
34.                Schedule = t.Schedule,
35.                Status = t.Status.ToString(),
36.                Result = t.LastResult,
37.                Exception = t.Exception?.Message,
38.                CreatedAt = DateTime.Now.AddMilliseconds(1)
39.            });

0
Michael
Top achievements
Rank 1
Veteran
Iron
answered on 27 Feb 2020, 10:18 AM

AppData is a static DTO

public static class AppData
{
    static AppData()
    {
        TaskList = new List<Logic.OceanTask>();
    }
 
    //public static IServiceProvider Instance { get; set; }
    public static List<Logic.OceanTask> TaskList { get; private set; }
    public static string AppPath { get; set; }
    public static string WWWRootPath { get; set; }
}
 
 
Tags
Grid
Asked by
Michael
Top achievements
Rank 1
Veteran
Iron
Answers by
Michael
Top achievements
Rank 1
Veteran
Iron
Abdullah
Top achievements
Rank 1
Alex Hajigeorgieva
Telerik team
Don
Top achievements
Rank 1
Dayanand
Top achievements
Rank 1
Share this question
or