Write Callback Result to Page - c#

I have been looking for hours trying to figure out how to write the result of my callback to my webpage. It is a rather specific problem but no solution I have ran across actually works. Here are the details:
Psuedo Code: (ideally)
User interacts with webpage (in this case, changing the bounds
within a google map).
Upon bounds_changed, javascript grabs the
bounds and sends them via a jquery callback in the JSON format to my
C# code.
The C# code processes the bounds and returns the searchResults in the form of JSON to webpage to be manipulated by javascript.
The second part of step 3 is the trouble spot (everything else works). I cannot seem to actually write the result dynamically on completion of the callback.
Here is the relevant code:
Send message from client to server: (this works but just including it for completeness)
function toServer(data) {
var dataPackage = data + "~";
jQuery('form').each(function () {
document.getElementById('payload').value = JSON.stringify({ sendData: dataPackage });
$.ajax({
type: "POST",
async: true,
url: window.location.href.toString(),
data: jQuery(this).serialize(),
success: function (result) {
console.log("callback compelete");
},
error: function(error) {
console.log("callback Error");
}
});
});
}
Server Code on page load: (note this does not work [the writing of the searchResults that is])
public Map_ResultsViewer_Beta(...)
{
...
//holds actions from page
string payload = HttpContext.Current.Request.Form["payload"] ?? String.Empty;
// See if there were hidden requests
if (!String.IsNullOrEmpty(payload))
{
//temp: process the request //2do: make this dynamic
string temp_AggregationId = CurrentMode.Aggregation;
string[] temp_AggregationList = temp_AggregationId.Split(' ');
Perform_Aggregation_Search(temp_AggregationList, true, Tracer);
//NOTHING BELOW THIS REALLY WORKS, ignore the the 'placeholder' method of displaying the results, it was just one attempt.
#region
// Start to build the response
StringBuilder mapSearchBuilder = new StringBuilder();
PlaceHolder MainPlaceHolder = new PlaceHolder();
mapSearchBuilder.AppendLine(" ");
mapSearchBuilder.AppendLine(" <script type=\"text/javascript\"> ");
mapSearchBuilder.AppendLine(" function processCallbackResult(){ ");
if (!string.IsNullOrEmpty(HttpContext.Current.Session["SearchResultsJSON"].ToString()))
{
mapSearchBuilder.AppendLine(" var searchResults=" + HttpContext.Current.Session["SearchResultsJSON"] + ";");
}
else
{
mapSearchBuilder.AppendLine(" var searchResults; ");
}
mapSearchBuilder.AppendLine(" } ");
mapSearchBuilder.AppendLine(" </script> ");
mapSearchBuilder.AppendLine(" ");
// Add this to the page
Literal writeData = new Literal { Text = mapSearchBuilder.ToString() };
MainPlaceHolder.Controls.Add(writeData);
#endregion
}
else
{
//string temp_AggregationId = CurrentMode.Aggregation;
//string[] temp_AggregationList = temp_AggregationId.Split(' ');
//Perform_Aggregation_Search(temp_AggregationList, true, Tracer);
HttpContext.Current.Session["SearchResultsJSON"] = "";
}
}
Actually performing the search: (this works, just putting it here for completeness)
public void Perform_Aggregation_Search(...)
{
//search the database for all items in all of the provided aggregations and merge them into one datatable
List<DataTable> temp_Tables = new List<DataTable>();
DataTable searchResults = new DataTable();
foreach (string aggregationId in aggregationIds)
{
temp_Tables.Add(Database.Get_All_Coordinate_Points_By_Aggregation(aggregationId, Tracer));
}
foreach (DataTable temp_Table in temp_Tables)
{
searchResults.Merge(temp_Table);
}
//assign and hold the current search result datatable, from now on we will be using this as the base layer...
HttpContext.Current.Session["SearchResults"] = searchResults;
//call json writer with these results
string searchResultsJSON = Create_JSON_Search_Results_Object(searchResults,Tracer);
//send json obj to page and tell page to read it (via callback results)
HttpContext.Current.Session["SearchResultsJSON"] = searchResultsJSON;
}
Code to create the JSON object: (this works, just putting it here for completeness)
public string Create_JSON_Search_Results_Object(...)
{
//take the search results from db query (incoming) and parse into JSON
JavaScriptSerializer serializer = new JavaScriptSerializer();
List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
Dictionary<string, object> row = null;
foreach (DataRow dr in searchResults.Rows)
{
row = new Dictionary<string, object>();
foreach (DataColumn col in searchResults.Columns)
{
row.Add(col.ColumnName.Trim(), dr[col]);
}
rows.Add(row);
}
//return JSON object
return serializer.Serialize(rows);
}
Did I miss anything? What am I doing wrong? Can you point me in the write direction?
Once again, the problem is in writing the result of the callback to the page.
Thanks!

You need to actually do something with the JSON in your success method of you ajax post.
You could use JQuery to target a DOM node like this:
$('.example').html(result);

Related

.NET MVC: perform heavy task on server then email user when complete so that user can leave site instead of wait?

The scenario: A button allows a user to merge a large number of PDF documents to download as a single PDF. Currently the action of getting all the PDF's and merging can take upwards of a minute or more while the user has to wait for the download to start.
My goal is to allow the user to leave if they want. The solution I thought of would be to merge the documents in the background on the server and then email a link to the user when it's completed but I'm open to other solutions.
The thing that I don't understand is how to perform the merging asynchronously in the background. Using .NET, MVC 5, DevExpress.
The code looks kinda like:
$.ajax({
type: "POST",
url: '#Url.Action("ExportMergedDocuments_PersonnelId", "Personnel", new { personnelId = Model.Id })',
}).done(function(data) {
window.location.href = '#Url.RouteUrl(new { Controller = "Personnel", Action = "Download"})/?file=' + data.fileName; }
});
[HttpPost]
public JsonResult ExportMergedDocuments_PersonnelId(int PersonnelId)
{
var allDocuments = new DataSet();
allDocuments.Merge(GetDocuments((int)PersonnelId, ".....1").Tables[0]);
allDocuments.Merge(GetDocuments((int)PersonnelId, ".....2").Tables[0]);
string fileName = $"merged__{DateTime.Now.ToString("yyyyMMddHHmm")}.pdf";
if (MergePdfSet(fileName, allDocuments))
return Json(new { fileName });
// else error msg
}
Download the file:
[HttpGet]
public ActionResult Download(string file)
{
return File(..fullpath.., "application/pdf", file);
}
Merging Pdfs:
public bool MergePdfSet(string fileName, DataSet allDocuments)
{
bool merged = false;
string fullPath = Path.Combine(Server.MapPath("~/App_Data/temp/"), fileName);
using (var pdfDocumentProcessor = new PdfDocumentProcessor())
{
pdfDocumentProcessor.CreateEmptyDocument(fullPath);
foreach (DataRow row in allDocuments.Tables[0].Rows)
{
var documentId = (int)row["DocumentID"];
var fetchedDocument = GetFile(documentId);
pdfDocumentProcessor.AppendDocument(fetchedDocument);
merged = true;
}
}
return merged;
}
Two option comes to mind:
Create a new thread and run the code there but don't await it.
Use Hangfire (https://www.hangfire.io/), you can easy enqueue a job.

I got System.FormatException from trying replacing a part of string with value

I have a javascript file and it contains below js script
(function() {
try {
var click = new MouseEvent('click', {bubbles: true, cancelable: true, view: window});
var field = document.querySelector('input[type="email"]');
setTimeout(function() {
field.dispatchEvent(click);
field.focus();
field.value="{0}";
}, 500);
return true;
} catch(err) {
return false;
}
})();
And I read that as string using below code:
var path = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory) + "\\Resources\\script\\myjavascript.js";
var raw = File.ReadAllText(path);
var args = new object[] { "my_username" };
Console.WriteLine(raw, args);
I got error: Exception thrown: 'System.FormatException' in mscorlib.dll
As I try to replace {0} with "my_username".
Can anybody help me?
Thanks.
Answer based on PepitoSh approach is below:
var path = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory) + "\\Resources\\script\\myjavascript.js";
var raw = File.ReadAllText(path);
var script = raw.Replace("{0}", "my_username");
Console.WriteLine(script);
You have to escape all other { and } and leave only "{0}" for the string.format to work.
Also I would add a js object with properties for all variables and use that as an argument or a global object in js scripts, so I only have to replace the values once for multiple scripts.
Since indeed you have to escape the curly braces that are not part of the formatting, I'd recommend another approach in this specific case:
var path = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory) + "\\Resources\\script\\myjavascript.js";
var raw = File.ReadAllText(path);
raw = raw.Replace("{0}", "my_username");
Console.WriteLine(raw);

Unity3d WebGL browser communication form

I have a program running through unity3d webGL, it works pretty well but I found getting feedback from people within the program is becoming a problem.
So I created a very basic form that the user can fill out in the program, press send and it will send to me.
My problem is that the information coming through is a sequence of numbers and not the messages.
Here is the various parts of the code if you spot something please let me know.
C# Unity3d form code
public void Send_help()
{
string the_date = DateTime.Now.ToString ("yyyy MMMMM dd");
string the_message = help_message.text;
string the_email = help_email.text;
Tcontroller.GetComponent<Trcontroller> ().Send_helpMessage (the_date,the_email,the_message);
Help_stuff.gameObject.SetActive (false);
audio.PlayOneShot (next);
}
The Send_helpMessage in the Tcontroller
private static extern void Message_help(string d, string e, string m);
[DllImport("__Internal")] //The imported function in my pluggin
public void Send_helpMessage(string date, string email, string message)
{
Message_help (date, email, message);
}
The pluggin code
var talk = {
Message_help: function(d,e,m)
{
Send_message_help(d,e,m);
}
};
mergeInto(LibraryManager.library, talk);
The website code
var this_date = '';
var this_email = '';
var this_message = '';
function Send_message_help(d,e,m)
{
this_date = d;
this_email = e;
this_message = m;
var Data = '&this_date='+this_date+'&this_email='+this_email+'&this_message='+this_message;
$.ajax({
url : "message.php",
type: "POST",
data : Data
});
};
Finally the pHp code
$MS = new mysqli ( $db_host, $db_username, $db_pass, $db_name );
$this_date = $_POST['this_date'];
$this_email = $_POST['this_email'];
$this_message = $_POST['this_message'];
$sqlupdate_user_message = "INSERT into contact(email, date, message) values('$this_email','$this_date','$this_message')";
mysqli_query ( $connMS, $sqlupdate_user_message );
mysqli_close($MS);
You can put any type of string value you want, the output to the database comes across as numbers
I know that WebGL is still new but it serves my purpose and everything else in terms of communication between webgl and the database has been fine with the exception of this form. Thanks for help in advance.
Please try this in plugin code(*.jslib):
var talk = {
Message_help: function(d,e,m)
{
var date = Pointer_stringify(d);
var email = Pointer_stringify(e);
var message = Pointer_stringify(m);
Send_message_help(date,email,message);
}
};
mergeInto(LibraryManager.library, talk);
When you send string from Unity WebGL to jslib, you need Pointer_stringify helper function to change it back to string. You can find more on this
link

Retrieve time zone/local times

Hello I would determine a method to input any kind of location data (I can cater it to just about anything) such as a city/state, a zip code, a street address etc. And get back the local time for that location.
Is that functionality build in somewhere or is there a good resource/class I can use already developed?
Thanks.
Ended up retrieving the search result from a Google search, since I did not have the lat/long.
User HTML Agility to extract the page contents, filtered the nodes that contained "Time", a simple enough the first item was the needed result.
If you google "time cincinnati oh" you get back "1:41pm Friday (EDT) - Time in Cincinnati, OH" at the top of the page. this code block extracts that. The safety is if the time is unable to be determined, the search page only shows the results, so the first item in the array is like, "Showing the results for "yourSearch"" etc.
public void timeZoneUpdate()
{
try
{
arrayToParse.Clear();
string URL = #"https://www.google.com/search?q=time+" + rowCity + "%2C+" + rowState;
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(URL);
myRequest.Method = "GET";
WebResponse myResponse = myRequest.GetResponse();
StreamReader sr = new StreamReader(myResponse.GetResponseStream(), System.Text.Encoding.UTF8);
string result = sr.ReadToEnd();
sr.Close();
myResponse.Close();
//Console.Write(result);
HtmlAgilityPack.HtmlDocument htmlSnippet = new HtmlAgilityPack.HtmlDocument();
htmlSnippet.Load(new StringReader(result));
bool foundSection = false;
foreach (HtmlAgilityPack.HtmlNode table in htmlSnippet.DocumentNode.SelectNodes("//table"))
{
foreach (HtmlAgilityPack.HtmlNode row in table.SelectNodes("tr"))
{
foreach (HtmlAgilityPack.HtmlNode cell in row.SelectNodes("td"))
{
if (cell.InnerText.Contains("Time"))
{
foundSection = true;
}
if (foundSection)
{
//Console.WriteLine("Cell value : " + cell.InnerText);
arrayToParse.Add(cell.InnerText);
}
}
}
}
retrievedTimeZone = arrayToParse[0].ToString().Split('-')[0].Trim();
if(retrievedTimeZone.Contains("Showing"))
{
retrievedTimeZone = "Undetermined";
}
}

Interacting with the Facebook C# SDK

Thanks to some of your patience and a small epiphany (sp?), I've now managed to get hold of the user object and groups etc. However, when I try to make calls to the api I notice my shortcomings (no, don't comment - I know you've noticed a while ago :p ). According to Facebook's docs, I should be able to post using something like
var body = 'Reading Connect JS documentation';
FB.api('/me/feed', 'post', { body: body }, function(response) {
if (!response || response.error) {
alert('Error occured');
} else {
alert('Post ID: ' + response);
}
});
However, translated to the SDK, I would assume I would do something like
app.Api("/me/feed", HttpMethod.Post);
but I don't see how I can send the text to write...
Also, while I'm at it - how would I go about using raw fql?
Any takers?
Thanks in advance :)
Well, while an interesting read, the link I was given here didn't really help. Was that the old Sdk?
Anyone know how to get to the elements in this?
JsonObject friends = app.Api("/me/friends") as JsonObject;
if (friends != null)
{
JsonArray friendsArr = friends["data"] as JsonArray;
for (int i = 0; i < friendsArr.Count(); i++ )
{
The data, as I got from the Graph doc is like this:
// me/friends:
//"data": [
// {
// "name": "Jan Voolstra",
// "id": "9013644"
// },
// {
// "name": "Christopher O'Rielly",
// "id": "9124229"
// },
All VS is telling me is that friendsArr[0] is of type Facebook.JsonObject with two elements...
Cheers!
var fb = new FacebookClient(_accessToken);
var arguments = new Dictionary<string, object>();
fb.PostCompleted += (o, args) =>
{
if (args.Error == null)
MessageBox.Show("Your status have been successfully posted to facebook!");
};
arguments["message"] = AboutTextBox.Text;
fb.PostAsync("me/feed", arguments);
How to get items from JsonObject:
List<string>names = new List<string>();
foreach (List<object> listresult in _result.Values)
{
foreach (JsonObject oneResult in listresult)
{
if (oneResult.ContainsKey("name"))
{
names.Add(oneResult["name"].ToString());
}
}
}
break;
}
I think this should work.

Categories