ASP.NET C# WebSocket - c#

I have created an ASP.NET C# project which consists of a web form and a WebSocket handler. I would like to send 2 data (name & price data) from the web form in JSON string format to the WebSocket handler. Here is the code snippet in the web form:
ws.onopen = function()
{
var name = "Client Product";
var price = 10.8;
ws.send(JSON.stringify(name));
ws.send(JSON.stringify(price));
alert("Message is sent...");
};
In the WebSocket handler's OnMessage(string) method, I would like to retrieve the 2 data sent by the web form and deserialize the 2 data to c# format. Here is the code snippet in the WebSocket handler:
public override void OnMessage(string message)
{
string serverName="";
string serverPrice = "";
serverName = JsonConvert.DeserializeObject<string>(message);
serverPrice = JsonConvert.DeserializeObject<string>(message);
}
However, under the WebSocket handler's onMessage(string) method, both the variable serverName and serverPrice would be assigned as "Client Product". I want the variable serverPrice to be assigned as "10.8", instead of "Client Product".
Can somebody please tell me how I could achieve that? WILL really appreciate if you could help me :) Thank You :)

If you want to send multiple pieces of data in a single JSON message, you'll need to combine them into an object. Try it like this:
On the client:
ws.onopen = function()
{
var obj = {
name: "Client Product",
price: "10.8"
};
ws.send(JSON.stringify(obj));
alert("Message is sent...");
};
On the server:
public override void OnMessage(string message)
{
MyData obj = JsonConvert.DeserializeObject<MyData>(message);
string serverName = obj.Name;
string serverPrice = obj.Price;
...
}
public class MyData
{
// Important: these JsonProperty attributes MUST match
// the names of the properties in the client object
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("price")]
public string Price { get; set; }
}

Related

HttpResponseMessage post API json format with C#

I used the HttpResponseMessage Post method to let the mobile terminal verify the account password. I used the following CODE to run successfully, but the POST format must be run like this.
'{"ID":"xxx","Password":"xxx"}'
It need two ' can run, I don't know why.
I can't request a service using the normal POST format on iOS or Android.
The format I want is {"ID":"xxx","Password":"xxx"},without '
[HttpPost]
public HttpResponseMessage Post([FromBody] string DATA)
{
using (appapidataEntities entities = new appapidataEntities())
{
//string controllerName = ControllerContext.RouteData.Values["controller"].ToString();
JObject jo = JObject.Parse(DATA);
string id = jo["ID"].ToString();
string password = jo["Password"].ToString();
var user = entities.USERs.Where(x => x.ID == id && x.Password == password).FirstOrDefault();
var result = new
{
message = "failure"
};
var result2 = new
{
message = "success"
};
if (user == null)
{
return Request.CreateResponse(HttpStatusCode.OK, result);
}
else
{
return Request.CreateResponse(HttpStatusCode.OK, result2);
}
}
}
public partial class USER
{
public string ID { get; set; }
public string Password { get; set; }
}
}
Please have someone with experience to help me, thank you very much.
As #Nkosi said, the correct way to receive a complex object is using a class/object (also called 'model binding')
In your models add this class. This class will be the 'contract' between the service with any external application who calls the service. Usually, any client (service, app or frontend) also has a class with this contract to call the service.
public class LoginViewModel {
public string ID { get; set; }
public string Password { get; set; }
}
Now, modify the controller as follow
[HttpPost]
public HttpResponseMessage Post([FromBody] LoginViewModel DATA) {
using (appapidataEntities entities = new appapidataEntities())
string id = DATA.ID;
string password = DATA.Password;
// rest of the code
}
}
Make sure the device is sending the data the service is waiting (maybe adding a breakpoint if you are debugging from Android Studio before to make the request) and add a breakpoint in your controller to verify that the variable DATA has the correct values.

How to convert Object and view it on WebAPI?

Here is my question,
I got a Web API and client(winform), client will send out data with a Serialize Object. My Web API do have received and return a response to client. But I can't view the data on Web API, I do have try using Deserialize Object and convert it into string but not working neither.
Please help me,Thanks!
Here is my code:
Client
private string WebApiPost(string sParam, string sJson)
{
var client = new HttpClient();
var content = new StringContent(sJson, Encoding.UTF8, "application/json");
var response = client.PostAsync(sWebAPI_URL + sParam, content).Result;
var body = response.Content.ReadAsStringAsync().Result;
return body;
}
This is my Web API
public object Post([FromBody]object hL7)
{
//what should I do???
//I've tried set hL7 into string but it wont get any data;
//I've also tried deserialize it but will get 500 internal server error.
return hL7;
}
This is my WebAPI model
public class HL7MID
{
public string LOC { get; set; }
public string COMPANY { get; set; }
}
public class HL7MID_List
{
public string sMSG { get; set; }
public List<HL7MID> data = new List<HL7MID>();
}
Because sJson matches HL7MID, you can use that type in as a paramter of your Post function, and just use that type.
public HL7MID Post([FromBody]HL7MID hL7)
{
//use hL7 here
return hL7;//also since you know the return type, changing that to HL7MID is suggested
}

Adding record to Zoho creator

Hi I am using following code to add a record to Zoho Creator form using asp.net c#.
However I receive in respose "The form has been removed from publish."
I have checked form at Zoho creator its working fine & has been published.
Please help me figure out the problem.
public partial class WebForm1 : System.Web.UI.Page
{
protected void btnSubmit_OnClick(object sender, EventArgs e)
{
var response = Http.Post("https://creator.zoho.com/saadelboury1/myfirstApp/form-perma/NEWDISTRIBUTOR/record/add/", new NameValueCollection() {
{ "authtoken", "<KEY>" },
{ "scope", "creatorapi" },
{ "First_Name", "John" },
{ "Last_Name", "Doe" },
{ "Email", "someone22#gmail.com" },
});
string result = System.Text.Encoding.UTF8.GetString(response);
Response.Write(result);
}
}
}
public static class Http
{
public static byte[] Post(string uri, NameValueCollection pairs)
{
byte[] response = null;
using (WebClient client = new WebClient())
{
response = client.UploadValues(uri, pairs);
}
return response;
}
Turned out, the url I was calling was wrong.
The correct url format is:
https://creator.zoho.com/api/[username]/xml/[application_name]/form/[form_name]/record/add/
Here I push the records from the school form to the student form with the help of add record task.
var = Insert into Student
[
Name = input.Name
Email = input.Email
Phone = input.Phone
Address = input. Address
];
Variable holding the ID of the new record.
<<form_link_name> Link name of the field for which the value is specified.
Value to be assigned to the field. You can directly specify a value, or you can specify an expression.

c# dictionary as a value of a hashtable

I have to code a little C# Console application (but my knowledge on .NET is almost NULL) to make a POST request to a PHP API, for which I'm using an HttpClient instance. The API accepts a JSON like this
{
"User": {
"email": "email#host.com",
"password": "something"
},
"Establishment": {
"id": 147
}
}
After doing some research on how to do this what I've done so far is this:
static async Task RunAsync()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://italdelo.web.development.co/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
try
{
// HTTP POST
Dictionary<string, string> user = new Dictionary<string, string>();
Dictionary<string, int> establishment = new Dictionary<string, int>();
HashTable postdata = new HashTable();
user.Add("email","email#host.com");
user.Add("password","something");
establishment.Add("id",147);
postdata.Add("User",user);
postdata.Add("Establishment",establishment);
HttpResponseMessage response = await client.PostAsJsonAsync("apiname/service", postdata);
response.EnsureSuccessStatusCode(); // Throw if not a success code.
}
catch (HttpRequestException e)
{
Console.WriteLine("Exception details: " + e.ToString());
}
}
}
Running this code I got this error message:
Severity Code Description Project File Line Suppression State Error CS0246 The type or namespace name 'HashTable' could not be found (are you missing a using directive or an assembly reference?) ProjectName C:\Users\...\Program.cs 47 Active
I know the error is the way I'm trying to setup the JSON to send to the API, which is a hashtable containing values (hashtable's key-value notation) as dictionaries. I'm pretty sure this is dumb but I don't really know how to setup this JSON for the API, I have no choice, I need to use C#. Can you help me please giving me some advice on how to fix this or get this done in another way? Thanks in advance.
you can create a class that will serve as parameter for consuming API.
//you classes
public class Parameter
{
public User user { get; set;}
public Establishment {get; set;}
}
public class User
{
public string email {get; set;}
public string password {get; set}
}
public class Establishment
{
public int id {get;set;}
}
//in your api calling method:
`var p = new Parameter
{
Establishment = new Establishment
{
id = 123
},
User = new User
{
email = "email",
password = "password"
}
};
HttpResponseMessage response = await client.PostAsJsonAsync("apiname/service", p);
Use c# anonymous classes
var payload = new{
User=new {
email= "email#host.com",
password= "something"
},
Establishment=new {
id= 147
}
}
then use newtonsoft json.net
var json = JsonConvert.SerializeObject(payload);
Looks like a typo, C# Hashtable does not capitalize the middle T:
https://msdn.microsoft.com/en-us/library/system.collections.hashtable(v=vs.110).aspx

D2L Valence: Auto-authentication in c# with app & user id/key

the below is my code.
I'm building a c# window app to obtain some information from url without having to log in but auto-log in.
It's window app form that will output course offerings when user clicks the accept button. This code is based on valence-client-side sample code. I want this app to log in with the app id/key pair and user id/key pair and get course offerings and output them. But, when I run this program, it just stops var ctx = httpListener.GetContext(); at this line. I don't want it to open a browser but want to get auto-log in with app and user id/key pair in c#, and get json response from the url. so users do not have to log in.
namespace CourseOfferingWindow
{
class CourseOfferingResponse
{
public string Identifier { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public bool IsActive { get; set; }
public string Path { get; set; }
public object StartDate { get; set; }
public object EndDate { get; set; }
public string CourseTemplate { get; set; }
public string Semester { get; set; }
public string Department { get; set; }
}
public partial class CourseOfferingWindowForm : Form
{
public CourseOfferingWindowForm()
{
InitializeComponent();
}
private static ID2LUserContext InterceptUserTokens(HostSpec host, ID2LAppContext appContext)
{
// Start HTTP server and listen for the redirect after a successful auth
var httpListener = new HttpListener();
httpListener.Prefixes.Add("http://localhost:31337/result/");
httpListener.Start();
// This call blocks until we get a response
var ctx = httpListener.GetContext();
// The LMS returns the user tokens via query parameters to the value provided originally in x_target
// TODO: deal with "failed to login" case
var userContext = appContext.CreateUserContext(ctx.Request.Url, host);
// Send some JavaScript to close the browser popup
// This is not 100% effective: for example, Firefox will ignore this.
const string RESPONSE = "<!doctype html><meta charset=\"utf-8\"><script>window.close();</script><h1>You may now close your window</h1><p>You may or may not see this message, depending on your browser</p>";
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(RESPONSE);
ctx.Response.ContentType = "text/html";
ctx.Response.ContentLength64 = buffer.Length;
ctx.Response.OutputStream.Write(buffer, 0, buffer.Length);
ctx.Response.OutputStream.Close();
httpListener.Stop();
return userContext;
}
private static void DoApiStuff(string host, ID2LUserContext userContext)
{
const string COURSEOFFERING_ROUTE = "/d2l/api/lp/1.0/courses/644849";
var client = new RestClient(host);
var valenceAuthenticator = new D2L.Extensibility.AuthSdk.Restsharp.ValenceAuthenticator(userContext);
var request = new RestRequest(COURSEOFFERING_ROUTE, Method.GET);
valenceAuthenticator.Authenticate(client, request);
var response = client.Execute<CourseOfferingResponse>(request);
Console.WriteLine("Hello, " + {course offerings information} );
}
private void ButtonAccept_Click(object sender, EventArgs e)
{
// This is the LMS we will interact with
var host = new HostSpec("https", "www.foltest.ca", 443);
// The appId/appKey come from our app.config - it is good to seperate access keys from the code that uses them.
// Ideally you wouldn't have production keys committed to source control.
string appId = ConfigurationManager.AppSettings["appId"];
string appKey = ConfigurationManager.AppSettings["appKey"];
// This is the port we will temporarily host a server on to intercept the user tokens after a successful login
int port = int.Parse(ConfigurationManager.AppSettings["serverPort"]);
// Create url for the user to login. If they have already done so they will not actually have to type their password (maybe).
var appContextFactory = new D2LAppContextFactory();
var appContext = appContextFactory.Create(appId, appKey);
var authUrl = appContext.CreateUrlForAuthentication(host, new Uri("http://localhost:" + port + "/result/"));
//OpenBrowser(authUrl);
// This call will block until we have a result
// TODO: you'll want better control flow and error handling here
var userContext = InterceptUserTokens(host, appContext);
// Now we can call Valence
DoApiStuff(host.Scheme + "://" + host.Host + ":" + host.Port, userContext);
// Pause the terminal
Console.ReadKey();
}
}
}
any kind of help will be appreciated. Thanks, Phillip
Instead of:
var authUrl = appContext.CreateUrlForAuthentication(host, new Uri("http://localhost:" + port + "/result/"));
//OpenBrowser(authUrl);
// call will block until we have a result
// TODO: you'll want better control flow and error handling here
var userContext = InterceptUserTokens(host, appContext);
// Now we can call Valence
DoApiStuff(host.Scheme + "://" + host.Host + ":" + host.Port, userContext);
do:
const string userId = "a_user_id"; // Use the correct user id
const string userKey = "a_user_key"; // Use the correct user key
var userContext = appContext.CreateUserContext(userId, userKey, host);
DoApiStuff(host.Scheme + "://" + host.Host + ":" + host.Port, userContext);
This assumes you have a Valence user id and key for the user account you want to use at your disposal. If you don't, you need to generate them out-of-band.

Categories