I was trying to make a register function using angularJS and webAPI
After registering , API should set a cookie. However when I reload the page there is no cookie! I don't know what is the problem!!!!
This is how I set the cookie
public HttpResponseMessage register(User UserToRegister)
{
UserToRegister.UserID = Guid.NewGuid();
YanceySiteDBEntities db = new YanceySiteDBEntities();
db.Users.Add(UserToRegister);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, UserToRegister);
var cookie = new CookieHeaderValue("useremail", UserToRegister.UserEmail);
cookie.Expires = DateTimeOffset.Now.AddDays(1);
cookie.Domain = Request.RequestUri.Host;
cookie.Path = "/";
response.Headers.AddCookies(new CookieHeaderValue[] { cookie });
return response;
}
And this is how I read the cookie.
public bool CheckIfLogIn()
{
bool LogedIn = false;
CookieHeaderValue cookie = Request.Headers.GetCookies("useremail").FirstOrDefault();
if (cookie != null) LogedIn = true;
return LogedIn;
}
Hope anyone can help me , Thanks in advance!
Related
I need a C# code that will trigger a nprinting task. On our server we are not allowed to evoke html file, hence I can't use javascript attached.
The attached works just need to translate it to .net as I can't use html on our server
Javascripts below works just fine
<html>
<head>
</head>
<body>
<h1>NPrinting API task starter</h1>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript">
(function(){
console.log("started")
var taskIDs=[
"f3ebd873-b310-4a22-a269-24ce81b8ce74"
]
$.ajax({
url: 'URL:4993/api/v1/login/ntlm',
xhrFields: {
withCredentials: true
}
}).done(function(data) {
console.log(data);
for(var i=0;i<taskIDs.length;i++){
$.ajax({
type: "POST",
url: 'URL:4993/api/v1/tasks/'+taskIDs[i]+'/executions',
xhrFields: {
withCredentials: true
}
}).done(function(data) {
console.log("task "+i);
console.log(data);
if(i==taskIDs.length)
open(location, '_self').close();
});
}
});
})();
<!-- open(location, '_self').close(); -->
</script>
</body>
</html>
C# code which I can't complete all the below works but doesn't start the task.
//Create the HTTP Request (authenticate) and add required headers
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL:4993/api/v1/login/ntlm");
CookieContainer cookies = new CookieContainer();
request.CookieContainer = cookies;
request.Method = "GET";
request.UserAgent = "Windows";
request.Accept = "application/json";
// specify to run as the current Microsoft Windows user
request.UseDefaultCredentials = true;
try
{
// make the web request and return the content
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader responseReader = new StreamReader(response.GetResponseStream());
string sResponseHTML = responseReader.ReadToEnd();
Console.WriteLine(sResponseHTML);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
//Create second HTTP request (get list of apps) and add required headers
HttpWebRequest secondRequest = (HttpWebRequest)WebRequest.Create(#"URL:4993/api/v1/tasks/f3ebd873-b310-4a22-a269-24ce81b8ce74/executions");
//assign cookie to request to maintain session
secondRequest.CookieContainer = cookies;
secondRequest.Method = "POST";
secondRequest.UserAgent = "Windows";
secondRequest.Accept = "application/json";
// specify to run as the current Microsoft Windows user
secondRequest.UseDefaultCredentials = true;
Thanks
I found a solution to the above, request.
Nprinting API task to run from C#
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace Post_Request_API
{
class Program
{
static void Main(string[] args)
{
//Create the HTTP Request (authenticate) and add required headers
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(#"URL:4993/api/v1/login/ntlm");
//Assign custom SSL certificate validation method if certificate is untrusted
//request.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
CookieContainer cookies = new CookieContainer();
request.CookieContainer = cookies;
request.Method = "GET";
request.UserAgent = "Windows";
request.Accept = "application/json";
//Specify to run as the current Microsoft Windows user
request.UseDefaultCredentials = true;
try
{
// make the web request and return the content
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader responseReader = new StreamReader(response.GetResponseStream());
string sResponseHTML = responseReader.ReadToEnd();
Console.WriteLine(sResponseHTML);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
//Create second HTTP request to add a new user and required headers
HttpWebRequest secondRequest = (HttpWebRequest)WebRequest.Create(#"URL:4993/api/v1/tasks/f3ebd873-b310-4a22-a269-24ce81b8ce74/executions");
//Assign custom SSL certificate validation method if certificate is untrusted
//secondRequest.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
//Add the XSRF token
secondRequest.Headers.Add("X-XSRF-TOKEN", cookies.GetCookies(request.RequestUri)["NPWEBCONSOLE_XSRF-TOKEN"].Value);
secondRequest.CookieContainer = cookies;
secondRequest.Method = "POST";
secondRequest.UserAgent = "Windows";
secondRequest.Accept = "application/json";
secondRequest.ContentType = "application/json";
//Specify to run as the current Microsoft Windows user
secondRequest.UseDefaultCredentials = true;
//Prepare JSON object to send to the remote server
JsonUser user = new JsonUser();
user.ID = "";
user.type = "";
user.task = "";
user.created = "";
user.lastUpdate = "";
user.completed = "";
user.progress = "";
user.status = "Enqueued";
user.result = "";
user.priority = "";
string jUserString = JsonConvert.SerializeObject(user);
using (var streamWriter = new StreamWriter(secondRequest.GetRequestStream()))
{
streamWriter.Write(jUserString);
streamWriter.Flush();
streamWriter.Close();
}
try
{
HttpWebResponse response2 = (HttpWebResponse)secondRequest.GetResponse();
StreamReader responseReader2 = new StreamReader(response2.GetResponseStream());
string sResponseHTML2 = responseReader2.ReadToEnd();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
public class JsonUser
{
public string ID { get; set; }
public string type { get; set; }
public string task { get; set; }
public string created { get; set; }
public string lastUpdate { get; set; }
public string completed { get; set; }
public string progress { get; set; }
public string status { get; set; }
public string result { get; set; }
public string priority { get; set; }
}
}
}
I have a problem with returning an error to html. So, I have web-app with "sql interpreter".
HTML
<button type="submit" onclick="executeSQL('interpreterSQL')">
<i class="fas fa-bolt"></i>
</button>
<textarea id="interpreterSQL" placeholder="❔❔❔"></textarea>
After entering a query into the interpreter, I run POST in javascript and shoot to spring:
POST in JavaScript
function executeSQL(interpreterSQL) {
var tmp = document.getElementById(interpreterSQL).value;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// Typical action to be performed when the document is ready:
var response = xhttp.responseText;
console.log("ok"+response);
}
};
xhttp.open("POST", "/user/executeSQL", true);
xhttp.send(tmp);
}
After that I handle the query in my service and return message to POST in my Controller:
Controller (POST in Spring)
#PostMapping(path = { "/user/executeSQL" })
public ModelAndView executeSQL(#RequestBody String tmp) {
String[] split = tmp.replace("\n", "").replace("\t", "").split(";");
String feedback = databaseTableService.executeSQL(split);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("successMessage", feedback);
modelAndView.setViewName("/user/interpreterSQL");
return modelAndView;
}
Service which is used to execute native query
public String executeSQL(String[] split){
SessionFactory hibernateFactory = someService.getHibernateFactory();
Session session = hibernateFactory.openSession();
String message = null;
for (int i = 0; i < split.length; i++) {
try{
String query = split[i];
session.doWork(connection -> connection.prepareStatement(query).execute());
message = "Success";
}
catch(Exception e){
message = ((SQLGrammarException) e).getSQLException().getMessage();
}
}
session.close();
return message;
}
So finally we are in my controller which is ready to return value and we have message which is have information about sql exceptions. We are there:
And here is my question: How to get variable "feedback" in response?
I need to handle that value there i think:
but that "var response = xhttp.responseText" is returning all my HTML code. I need only parametr "feedback" from my controller.
Guys can someone help? :( I don't know how to send that parametr in return and handle it in javascript...
Maybe you can change your Controler method to return JSON response instead on ModelAndView
#PostMapping(path = { "/user/executeSQL" })
public ResponseEntity<Object> executeSQL(#RequestBody String tmp) {
String[] split = tmp.replace("\n", "").replace("\t", "").split(";");
Map<String,String> response = new HashMap<String, String>();
response.put("feedback", databaseTableService.executeSQL(split));
return new ResponseEntity<>( response , HttpStatus.OK);
}
Now you should be able to see the status
var response = xhttp.responseText;
console.log("ok"+response);
I'm trying to resolve an issue between, what I perceive is, AJAX and Server Sent Events. I have an application that does a post with some instructions to the controller, and I would like the controller to send some commentary back as an event to let the user know that the action requested has been performed (can have errors or take a while).
The idea is that the user can send a package of different instructions through the client, and the server will report through SSE when each of these actions are completed.
The problem I see through Fiddler is that when the post is performed, the response that it gets back contains my eventsource message that I would like used. However, the eventsource code also appears to call a GET, in which it appears to want that eventsource message. Because it doesn't get that, the connection repeatedly closes.
I currently have some controller code like so:
[System.Web.Http.HttpPost]
public void Stop(ProjectViewModel model)
{
ProjectManager manager = new ProjectManager();
if (model.Servers != null && model.Servers.Count != 0)
{
string machine = model.Servers[0];
foreach (string service in model.Services)
{
manager.StopService(service, machine);
Message("stop", service);
}
}
}
and in my view, both Ajax/XHR and server sent events set up like so:
var form = document.getElementById("submitform");
form.onsubmit = function (e) {
// stop the regular form submission
e.preventDefault();
// collect the form data while iterating over the inputs
var data = {};
for (var i = 0, ii = 2; i < ii; ++i) {
var input = form[i];
if (input.name == "Servers") {
data[input.name] = document.getElementById("ServerSelect").options[document.getElementById("ServerSelect").selectedIndex].text;
}
else if (input.name == "Services")
data[input.name] = document.getElementById("ServiceSelect").options[document.getElementById("ServiceSelect").selectedIndex].text;
}
if (action) { data["action"] = action };
// construct an HTTP request
var xhr = new XMLHttpRequest();
if (action == "stop") {
xhr.open(form.method, '/tools/project/stop', true);
}
if (action == "start") {
xhr.open(form.method, '/tools/project/start', true)
}
xhr.setRequestHeader('Content-Type', 'application/json; charset=urf-8');
// send the collected data as JSON
xhr.send(JSON.stringify(data));
xhr.onloadend = function () {
// done
};
};
function events() {
if (window.EventSource == undefined) {
// If not supported
document.getElementById('eventlog').innerHTML = "Your browser doesn't support Server Sent Events.";
} else {
var source = new EventSource('../tools/project/Stop');
source.addEventListener("message", function (message) { console.log(message.data) });
source.onopen = function (event) {
document.getElementById('eventlog').innerHTML += 'Connection Opened.<br>';
console.log("Open");
};
source.onerror = function (event) {
if (event.eventPhase == EventSource.CLOSED) {
document.getElementById('eventlog').innerHTML += 'Connection Closed.<br>';
console.log("Close");
}
};
source.onmessage = function (event) {
//document.getElementById('eventlog').innerHTML += event.data + '<br>';
var newElement = document.createElement("li");
newElement.textContent = "message: " + event.data;
document.getElementById("eventlog").appendChild(newElement)
console.log("Message");
};
}
};
I'm somewhat new to web development, and I'm not sure how to resolve this issue. Is there a way I can have the eventsource message read from that POST? Or have it sent to the GET instead of being sent as a response to the POST? Overall, it seems that the most damning issue is that I can't seem to get the event messages sent to the GET that is requested by the eventsource api.
EDIT: Since posting this, I tried creating a new method in the controller that specifically handles eventsource requests, but it appears that the event response still somehow ends up in the POST response body.
public void Message(string action, string service)
{
Response.ContentType = "text/event-stream";
Response.CacheControl = "no-cache";
//Response.Write($"event: message\n");
if (action == "stop")
{
Response.Write($"data: <li> {service} has stopped </li>\n\n");
}
Response.Flush();
Thread.Sleep(1000);
Response.Close();
}
I ended up solving this. My original idea was to pass the viewmodel in each of my methods back and forth with a Dictionary<string,string> to key in each event that can be used, but the viewmodel is not persistent. I solved this issue further by implementing the events in a Dictionary saved in Session data, and the usage of Sessions for MVC can be found in the resource here that I used:
https://code.msdn.microsoft.com/How-to-create-and-access-447ada98
My final implementation looks like this:
public void Stop(ProjectViewModel model)
{
ProjectManager manager = new ProjectManager();
if (model.Servers != null && model.Servers.Count != 0)
{
string machine = model.Servers[0];
foreach (string service in model.Services)
{
manager.StopService(service, machine);
model.events.Add(service, "stopped");
this.Session["Events"] = model.events;
}
}
//return View(model);
}
public void Message(ProjectViewModel model)
{
Thread.Sleep(1000);
Response.ContentType = "text/event-stream";
Response.CacheControl = "no-cache";
Response.AddHeader("connection", "keep-alive");
var events = this.Session["Events"] as Dictionary<string, string>;
Response.Write($"event: message\n");
if (events != null && events.Count != 0)
{
foreach (KeyValuePair<string, string> message in events)
{
Response.Write($"data: {message.Key} has been {message.Value}\n\n");
}
}
Response.Flush();
Thread.Sleep(1000);
Response.Close();
}
Adding keep-alive as connection attribute in the HTTP Response header was also important to getting the SSEs to send, and the Thread.Sleep(1000)'s are used due to the stop action and message action happening simultaneously. I'm sure there's some optimizations that can go into this, but for now, this is functional and able to be further developed.
I'm using the code below for downloading with the web API in ASP.NET.
When I'm trying to click the download button, it calls the API.
After executing the "DownloadFile"-function, the download dialog box isn't coming .
[HttpGet]
public HttpResponseMessage DownloadFile(string DownloadFilePath)
{
HttpResponseMessage result = null;
var localFilePath = HttpContext.Current.Server.MapPath(DownloadFilePath);
// check if parameter is valid
if (String.IsNullOrEmpty(DownloadFilePath))
{
result = Request.CreateResponse(HttpStatusCode.BadRequest);
}
// check if file exists on the server
else if (!File.Exists(localFilePath))
{
result = Request.CreateResponse(HttpStatusCode.Gone);
}
else
{// serve the file to the client
result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read));
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = DownloadFilePath;
}
return result;
}
I didn't get any exception from the code above, but the dialog box for downloading the file isn't coming.
Here is the code, I am using and it works great. I hope it will give you an idea
....
var fileBytes = Helper.GetFileBytes(filePath);//convert file to bytes
var stream = new MemoryStream(fileBytes);
resp.Content = new StreamContent(stream);
resp.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
resp.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = filerequest.FileName };
resp.Content.Headers.Add("Content-Encoding", "UTF-8");
return resp;
And, here is the code for GetFileBytes method,
public static byte[] GetFileBytes(string filePath)
{
var fileInfo = new FileInfo(filePath);
if (fileInfo.Exists)
{
return File.ReadAllBytes(fileInfo.FullName);
}
return null;
}
Server side:
public override Task OnConnected()
{
var connectionId = Context.ConnectionId;
var user = Context.User.Identity.Name; // Context.User is NULL
return base.OnConnected();
}
Client side (in Console project):
IHubProxy _hub;
string url = #"http://localhost:8080/";
var connection = new HubConnection(url);
_hub = connection.CreateHubProxy("TestHub");
connection.Start().Wait();
When the client connect to the server, I want to know the map between userName and connectionId, But Context.User is NULL. How do I set this value in the client side?
try this with queryString in asp.netcore 2.1:
Client (javascript)
set query string after url like follow:
var connection = new signalR.HubConnectionBuilder().withUrl("http://localhost:10499/chathub?username=xxxx").build();
connection.start().then(function ()
{
// do some thing here ...
}).catch(function (err)
{
console.error(err.toString());
});
.
.
.
Server
public override Task OnConnectedAsync()
{
var username = Context.GetHttpContext().Request.Query["username"];
// username = xxxx
return base.OnConnectedAsync();
}
Pass your username using query string.
Client
First set query string
string url = #"http://localhost:8080/";
var connection = new HubConnection(url);
_hub = connection.CreateHubProxy("TestHub");
connection.qs = { 'username' : 'anik' };
connection.Start().Wait();
Server
public override Task OnConnected()
{
var username= Context.QueryString['username'];
return base.OnConnected();
}
Client
var connection = new HubConnection(<YOUR_URL>);
connection.Headers.Add("username", "maria");
var myHub = connection.CreateHubProxy("MyHub");
Server
string username = Context.Headers.Get("username");
Console.WriteLine("New client connection - " + username);
If your using basic authentication create a new System.Net.NetworkCredential
string url = #"http://localhost:8080/";
var connection = new HubConnection(url);
NetworkCredential myCredentials = new NetworkCredential("","","");
myCredentials.Domain = "domain";
myCredentials.UserName = "username";
myCredentials.Password = "passwd";
connection.Credentials = myCredentials;
_hub = connection.CreateHubProxy("TestHub");
connection.Start().Wait();
See: https://learn.microsoft.com/en-us/dotnet/api/system.net.networkcredential.username?view=net-6.0
try this
Client (C#)
//Enter query string
var querystringData = new Dictionary<string, string>();
querystringData.Add("username", "naveed");
IHubProxy _hub;
string url = #"http://localhost:8080/";
var connection = new HubConnection(url);
_hub = connection.CreateHubProxy("TestHub");
connection.Start().Wait();
connection.Start().Wait();
Server
public override Task OnConnected()
{
var connectionId = Context.ConnectionId;
var username= Context.QueryString["username"]; //here you will receive naveed as username
return base.OnConnected();
}