I have a ASP.NET Core MVC 5 website. I am using SignalR to send "Notifications" from the model layer to the client / view.
If I open my index page, It uses SignalR to send a list of available cameras as they are discovered. I then again use SignalR to send images that the camera is taking on a different model. However, only the first one works.
If I navigate to https://localhost:44303/camera/live/?IP=192.168.50.212 It starts sending images, but will not discover other cameras. If I navigate to the discovery first, the discovery works just fine.
In both the models, the line Hub.Clients.All.SendAsync("method", data); is executing. In both models, the Hub is defined as
public Microsoft.AspNetCore.SignalR.IHubContext<MasterHub> Hub { get; internal set; }`
and each model has a separate controller, that sets the hub context like so:
private readonly IHubContext<MasterHub> _hubContext;
public CameraController(IHubContext<MasterHub> hubContext)
{
_hubContext = hubContext;
}
However, only the first one I navegate to works.
Do I have to close the SignalR connection after sending a message to use it again? If so, How would I do this?
both controllers look like:
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Thermal_Screening.Hubs;
using Thermal_Screening.Models;
namespace Thermal_Screening.Controllers
{
public class CameraController : Controller
{
public string CameraName;
private readonly IHubContext<MasterHub> _hubContext;
public CameraController(IHubContext<MasterHub> hubContext)
{
_hubContext = hubContext;
}
public IActionResult Live(string IP)
{
CameraName = getCameraNameFromIP(IP); // doin it this way causes a 2s delay, should get ip in model
return View(new CameraViewModel(IP) { Hub = _hubContext, IP = IP, CameraName = CameraName });
}
public IActionResult Settings(string IP)
{
CameraName = getCameraNameFromIP(IP);
return View(new CameraViewModel(IP) { Hub = _hubContext, IP = IP, CameraName = CameraName });
}
public IActionResult Log(string IP)
{
CameraName = getCameraNameFromIP(IP);
return View(new CameraViewModel(IP) { Hub = _hubContext, IP = IP, CameraName = CameraName });
}
private string getCameraNameFromIP(string IP)
{
WebClient x = new WebClient();
string source = x.DownloadString("http://" + IP);
return Regex.Match(source, #"\<title\b[^>]*\>\s*(?<Title>[\s\S]*?)\</title\>", RegexOptions.IgnoreCase).Groups["Title"].Value;
}
}
}
both viewmodels look like:
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Extensions;
using Flir.Atlas.Live.Discovery;
using Flir.Atlas.Live.Device;
using Flir.Atlas.Live;
using System.IO;
using Flir.Atlas.Image;
using System.Drawing;
using Microsoft.AspNetCore.SignalR;
using Thermal_Screening.Hubs;
namespace Thermal_Screening.Models
{
public class CameraViewModel
{
public Microsoft.AspNetCore.SignalR.IHubContext<MasterHub> Hub { get; internal set; }
//removed for berevity
Hub.Clients.All.SendAsync("method", "data");
Related
I have a weird error in Redis on .Net 6. When I run the test code here:
https://github.com/redis-developer/redis-graph-dotnet-basic-app/blob/main/Program.cs
It works perfectly fine. In this case the code is running in the program.cs file.
When I port that code to a class, in order to better manage encapsulation and complexity. It does not work. What it does is run the code and when it gets to the: await graph.QueryAsync part, it just stops the debugger. Very strange indeed.
Here is the code I am using. Any thoughts or suggestions:
//Program.cs (Relevant Bits)
using RedisTest //PROGRAM //WRITE TO REDIS ENTERPRISE CLOUD Process_LoadGraph process_LoadGraph = new Process_LoadGraph(); process_LoadGraph.Controller(results);
//SHARED CONNECTION CLASS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StackExchange.Redis;
namespace RedisTest
{
public class RedisSharedConnection
{
public static ConnectionMultiplexer Connection
{
get
{
return lazyConnection.Value;
}
}
private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
ConnectionMultiplexer connectionMultiplexer = ConnectionMultiplexer.Connect(ConfigData.dbConnectionString);
return connectionMultiplexer;
});
}
}
//USAGE CLASS
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NRedisGraph;
namespace RedisTest
{
public class Process_LoadGraph
{
public async void Controller(List<Result> results)
{
//Setup
var redisConnection = RedisSharedConnection.Connection;
//var redisConnection = ConnectionMultiplexer.Connect(ConfigData.dbConnectionString);
var db = redisConnection.GetDatabase(ConfigData.dbId);
var graph = new RedisGraph(db);
string graphName = ConfigData.graphName;
//Test Transaction
// Create Bob
// CRASHES HERE
var createBobResult = await graph.QueryAsync("pets", "MERGE(:human{name:'Bob',age:32})");
}
}
}
Turns out the solution is to use Redis in a static class. Along the following lines:
internal static class WriteToDB
{
public static async Task WriteAsync(List<string> querieS)
{
//Load Graph
//Setup
var redisConnection = RedisSharedConnection.Connection;
//var redisConnection = ConnectionMultiplexer.Connect(ConfigData.dbConnectionString);
var db = redisConnection.GetDatabase(ConfigData.dbId);
var graph = new RedisGraph(db);
string graphName = ConfigData.graphName;
// ** DEBUG
//Test Transaction
// Create Bob
var createBobResult = await graph.QueryAsync("pets", "MERGE(:human{name:'Bob',age:32})");
{ }
//Clear Graph
await graph.QueryAsync(graphName, "MATCH(n) DETACH DELETE n");
{ }
}
}
I have the following:
public class StripeController : Controller
{
private readonly UserService _userService;
public StripeController(UserService userService)
{
_userService = userService;
}
[HttpPost]
public ActionResult StripeWebook()
{
return new HttpStatusCodeResult(HttpStatusCode.OK);
}
[HttpPost]
[Route("api/stripewebhook")]
public async Task<ActionResult> Index(CancellationToken ct)
{
var json = new StreamReader(Request.InputStream).ReadToEnd();
var stripeEvent = StripeEventUtility.ParseEvent(json);
switch (stripeEvent.Type)
{
case StripeEvents.ChargeRefunded: // all of the types available are listed in StripeEvents
var stripeCharge = Stripe.Mapper<StripeCharge>.MapFromJson(stripeEvent.Data.Object.ToString());
break;
}
return new HttpStatusCodeResult(HttpStatusCode.OK);
}
}
And requests from stripe generate an error:
The controller for path '/api/stripewebhook' was not found or does not implement IController
Any idea why this is happening when I test from the stripe portal?
Using WebApi 2 it works with no problem.
Here is the smallest WebApi controller to begin with:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
namespace WebApplication1.Controllers
{
public class StripeController : ApiController
{
[HttpPost]
[Route("api/stripewebhook")]
public IHttpActionResult Index()
{
var json = new StreamReader(HttpContext.Current.Request.InputStream).ReadToEnd();
return Ok();
}
}
}
if you execute this from VS you can access it from http://localhost:(port)/api/stripewebhook
Now you only need to extend this to include the stripe code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
namespace WebApplication1.Controllers
{
public class StripeController : ApiController
{
[HttpPost]
[Route("api/stripewebhook")]
public IHttpActionResult Index()
{
var json = new StreamReader(HttpContext.Current.Request.InputStream).ReadToEnd();
var stripeEvent = StripeEventUtility.ParseEvent(json);
switch (stripeEvent.Type)
{
case StripeEvents.ChargeRefunded: // all of the types available are listed in StripeEvents
var stripeCharge = Stripe.Mapper<StripeCharge>.MapFromJson(stripeEvent.Data.Object.ToString());
break;
}
return Ok();
}
}
}
Good Day Everyone. I'm creating a simple Xamarin.Forms Portable Application in my Visual Studio 2015.
I want my Mobile Application to connect to the SQL Database I have in my VS2015 and return a LIST OF CUSTOMERS which should be display to my mobile phone.
I have created a Xamarin Portable project and a WebForms project that will handle my Web Services and Database.
In my WebForms project, I created a Controller that should return the List of Customers. This has a web service URL api/Customer that I used to connect to the RestClient in my Xamarin Portable. I also have CustomerViewModel that should represent the data in my application.
In my Xamarin Portable project, I have a ClientList.xaml that should display the List that comes from my database. I also have a CustomerVM that is connected to Services and my RestClient. My RestClient used the WEB SERVICE URL to get the List of Customer from my WebForms project.
Based on the given steps above, I still wasn't able to display the Data in my mobile phone. What do you think is the reason behind this? Thanks for your help.
Here are some of my codes:
RestClient.cs
public class RestClient_Customer<T>
{
private const string WebServiceUrl = "http://localhost:50857/api/Customer/";
public async Task<List<T>> GetCustomerAsync()
{
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var json = await httpClient.GetStringAsync(WebServiceUrl);
var taskModels = JsonConvert.DeserializeObject<List<T>>(json);
return taskModels;
}
}
CustomerServices.cs
using Plugin.RestClient;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using XamarinFormsDemo.Models;
namespace XamarinFormsDemo.Services
{
public class CustomerServices
{
public async Task<List<Customer>> GetCustomerAsync()
{
RestClient_Customer<Customer> restClient = new RestClient_Customer<Customer>();
var customerList = await restClient.GetCustomerAsync(); //yung getasync ay pantawag as restclient
return customerList;
}
}
}
CustomerVM.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
using XamarinFormsDemo.Models;
using XamarinFormsDemo.Services;
using XamarinFormsDemo.Views;
namespace XamarinFormsDemo.ViewModels
{
public class CustomerVM : INotifyPropertyChanged
{
private List<Customer> _customerList; // keep all customers
private List<Customer> _searchedCustomerList; // keep a copy for searching
private Customer _selectedCustomer = new Customer();
private string _keyword = "";
public string Keyword
{
get
{
return _keyword;
}
set
{
this._keyword = value;
// while keyword changed we filter Employees
//Filter();
}
}
private void Filter()
{
if (string.IsNullOrWhiteSpace(_keyword))
{
CustomerList = _searchedCustomerList;
}
else
{
// var lowerKeyword = _keyword.ToLower();
CustomerList = _searchedCustomerList.Where(r => r.CUSTOMER_NAME.ToLower().Contains(_keyword.ToLower())).ToList();
// EmployeesList = _searchedEmployeesList.Where(r => r.EMPLOYEE_NAME.Contains(_keyword)).ToList();
}
}
public List<Customer> CustomerList
{
get
{
return _customerList;
}
set
{
_customerList = value;
OnPropertyChanged();
}
}
public CustomerVM()
{
InitializeDataAsync();
}
private async Task InitializeDataAsync()
{
var customerServices = new CustomerServices();
_searchedCustomerList = await customerServices.GetCustomerAsync();
CustomerList = await customerServices.GetCustomerAsync();
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I think the problem is in your services hope this will help you,
public interface ICustomer
{
Task<string> GetCustomers();
}
public class CustomerService : ICustomer
{
public async Task<string> GetCustomers()
{
var client = new HttpClient();
var response = await client.GetAsync(string.Format("http://mysite/api/Customer"));
var responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
}
Call it anywhere you like
var _custList = new GetCustomers();
var returnJson = await _custList.GetCustomers();
Note the return is json string format or xml format depending on your REST API so you need to parse this first before you can get the value and display it to ListView
Try running it in UWP. If it works in UWP then you have to take a look at
Xamarin HttpClient.GetStringAsync not working on Xamarin.Droid
I had the same issue but when I tried it in UWP it worked fine. I am still seeking for the solution to run xamarin.android using device.
I am trying to write a simple chat application with iOS and Android clients. I am following the tutorial here http://blogs.msdn.com/b/youssefm/archive/2012/07/17/building-real-time-web-apps-with-asp-net-webapi-and-websockets.aspx to use WebSockets. However, I need to be able to send messages to a single "Chatroom" rather than broadcast to all the users (in reality there will only ever be 2 users, me and the person I'm chatting with). Currently I am doing this:
using Microsoft.Web.WebSockets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
namespace ChatPractice.Controllers
{
public class ChatController : ApiController
{
public HttpResponseMessage Get(string username, int roomId)
{
HttpContext.Current.AcceptWebSocketRequest(new ChatWebSocketHandler(username, roomId));
return Request.CreateResponse(HttpStatusCode.SwitchingProtocols);
}
}
class ChatWebSocketHandler : WebSocketHandler
{
private static WebSocketCollection _chatClients = new WebSocketCollection();
private string _username;
private int _roomId;
public ChatWebSocketHandler(string username, int roomId)
{
_username = username;
_roomId = roomId;
}
public override void OnOpen()
{
_chatClients.Add(this);
}
public override void OnMessage(string message)
{
var room = _chatClients.Where(x => ((ChatWebSocketHandler)x)._roomId == _roomId);
message = _username + ": " + message;
foreach (var user in room)
user.Send(message);
//_chatClients.Broadcast(_username + ": " + message);
}
}
}
Is using linq to get the correct room here correct or is there a better way to get to it?
This is an example of a chat server using WebSockets: Chat application using Reactive Extennsions.
It uses another WebSocket framework, but the idea should be pretty much the same.
It's better to use SignalR. There's a lot of tutorials online.
I am trying to create a web api with forms based authentication. I want to login from a client and retrieve data from there. When I log in, user gets authenticated and can retrieve data by giving http request direct into adressbar like localhost:1393/api/Game. But when i try to get it from client I am getting a 401 (Unauthorized error). I have enabled CORS in server side. This is the controller to handle data
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
using System.Web.Security;
using Cheeky_backend.Models;
using System.Web.Http.WebHost;
namespace Cheeky_backend.Controllers
{
public class Demo
{
public List<Teams> team { get; set; }
public List<Hole> hole { get; set; }
}
[Authorize]
public class GameController : ApiController
{
private Cheeky_backendContext db = new Cheeky_backendContext();
// GET api/Game
public IEnumerable<Hole> GetHoles()
{
return db.Holes.AsEnumerable();
}
}
}
This is the authenticating controler
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Security;
using System.Web.Http;
using Cheeky_backend.Models;
namespace Cheeky_backend.Controllers
{
public class UserController : ApiController
{
private Cheeky_backendContext db = new Cheeky_backendContext();
// GET api/Default1
// GET api/Default1/5
// PUT api/Default1/5
// POST api/Default1
public HttpResponseMessage CreateUser(User user)
{
if (ModelState.IsValid)
{
db.Users.Add(user);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, user);
// response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = user.ID }));
return response;
}
else
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
}
// DELETE api/Default1/5
public HttpResponseMessage Login(User user)
{
var userfound = from user2 in db.Users
where user.username == user2.username && user.password == user2.password
select user2;
if( userfound.Any())
{
FormsAuthentication.SetAuthCookie(user.username, true);
return Request.CreateResponse(HttpStatusCode.OK,user);
}
return Request.CreateResponse(HttpStatusCode.Unauthorized);
}
}
}
Source
In your Authentication Handler
Don't set the Principal on the Thread.CurrentPrinicipal any more.
Use the Principal on the HttpRequestContext.
Take a look at here