Updating database call without having to refresh page - c#

A list of images (treasures) are displayed to the user, here the user will choose a single image which will be stored in the Learner_treauser table:
List<The_Factory_Chante.Models.Treasure> tresh;
using (The_Factory_Chante.Models.The_FactoryDBContext db2 = new The_Factory_Chante.Models.The_FactoryDBContext())
{
string imageSource = "";
tresh = db2.Treasures.ToList();
foreach (var item in tresh)
{
if (item.itemImage != null)
{
string imageBase = Convert.ToBase64String(item.itemImage);
imageSource = string.Format("data:image/gif;base64,{0}", imageBase);
}
<img id="#item.treasureID" src="#imageSource" onclick="return MakeSure(#item.treasureID)" />
}
}
The function called when an image is chosen. In this function the image is sent over to a webservice method to be saved to the database, and the page is reload for an update to take place:
function MakeSure(treshID) {
var id = treshID
$.ajax({
url: "../../WebService.asmx/MakeSure",
data: "{ 'id': '" + id + "'}",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
success: function (data) {
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
}
});
window.location.reload();
};
However this is not very pleasant on the user's point of you. A better way would be to update without refreshing the page.
Here is the Webservice method that receives the chosen image id and stores it in the Learner_Treasure table.
public void MakeSure(int id)
{
using (The_FactoryDBContext db = new The_FactoryDBContext())
{
Learner_Treasure learnTreasure = new Learner_Treasure();
learnTreasure.dateCompleted = DateTime.Today;
learnTreasure.learnerID = UserInfo.ID;
learnTreasure.treasureID = id;
db.Learner_Treasure.Add(learnTreasure);
db.SaveChanges();
}
Code to call Learner_Treasure table.
List<The_Factory_Chante.Models.Learner_Treasure> lern;
using (The_Factory_Chante.Models.The_FactoryDBContext db2 = new The_Factory_Chante.Models.The_FactoryDBContext())
{
string imageSource = "";
lern = db2.Learner_Treasure.ToList();
if (lern != null)
{
foreach (var item in lern)
{
if (item.learnerID == UserInfo.ID)
{
byte[] bytes = db2.Treasures.FirstOrDefault(au => au.treasureID == item.treasureID).itemImage;
string imageBase = Convert.ToBase64String(bytes);
imageSource = string.Format("data:image/gif;base64,{0}", imageBase);
<img id="#item.treasureID" src="#imageSource"/>
}
}
This code will show the user all the images they have chosen, however in if I take away window.location.reload(); this code is only updated when the page reloads. Meaning that the user will not see their chosen image immediately after they have chosen it.
What I want to do is update the code that calls the Learner_Table without refreshing the page.

There is another way to approach this problem, you could use the SignalR library.
This is what you would need to do:
View
// Include the SignalR Script
<script src="~/Scripts/jquery.signalR-2.2.0.js"></script>
// Provide a dynamic proxy for SignalR
<script src="~/signalr/hubs"></script>
// Define hub connection(see below)
var hub = $.connection.yourHub;
// This is what the Hub will call (Clients.All.getImage(imageSource);)
hub.client.getImage = function (img) {
var image = '<img id="' + img.treasureId + '" src="data:image/jpg;base64,' + img.image + '"';
$(image).appendTo("body");
};
// Start the connection to the hub
// Once we have a connection then call the getLearnerTreasureItem on the Hub
$.connection.hub.start().done(function () {
var id = // whatever
hub.server.getLearnerTreasureItem(id);
};
Hub
public class YourHub : Hub
{
public void GetLearnerTreasureItem()
{
// All your code
List<The_Factory_Chante.Models.Learner_Treasure> lern;
using (The_Factory_Chante.Models.The_FactoryDBContext db2 = new The_Factory_Chante.Models.The_FactoryDBContext())
{
string imageSource = "";
lern = db2.Learner_Treasure.ToList();
if (lern != null)
{
foreach (var item in lern)
{
if (item.learnerID == UserInfo.ID)
{
byte[] bytes = db2.Treasures.FirstOrDefault(au => au.treasureID == item.treasureID).itemImage;
string imageBase = Convert.ToBase64String(bytes);
imageSource = string.Format("data:image/gif;base64,{0}", imageBase);
}
}
// This will now call the getImage function on your view.
Clients.All.getImage(imageSource);
}
}
Information on the dynamic proxy

The way I approach this is by making a partial View for the code that needs to be refreshed
public PartialViewResult UserImages(your paramaters here)
{
your code here
}
And then after successful $.ajax I refresh it
var id = treshID
$.ajax({
url: "../../WebService.asmx/MakeSure",
data: "{ 'id': '" + id + "'}",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
success: function (data) {
$.ajax({
url: "/UserImages",
data: your data model here,
success(function(html)){
$("#yourPartialViewWrapperHere").html(html));
}
});
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
}
});

Your problem is the onclick event handler here:
<img id="#item.treasureID" src="#imageSource" onclick="return MakeSure(#item.treasureID)" />
In the MakeSure() function you don't return anything. So you have two options, change your MakeSure() function to return false at the end, or change the onclick event to return false after the first function call in the image element, like this onclick="MakeSure(#item.TreasureID); return false;"
Also you will have to remove the window.location.reload(); from the MakeSure() function.
Side note, it seems you are mixing up your DbContext in your view, if that's the case, this is very bad practice. You should put your data access behind some sort of service layer that serves as a mediator between the view and your data.
Update
Ok after reading your question a few times I understand your problem
The problem is your second piece of code.
List<The_Factory_Chante.Models.Learner_Treasure> lern;
using (The_Factory_Chante.Models.The_FactoryDBContext db2 = new The_Factory_Chante.Models.The_FactoryDBContext())
{
string imageSource = "";
lern = db2.Learner_Treasure.ToList();
if (lern != null)
{
foreach (var item in lern)
{
if (item.learnerID == UserInfo.ID)
{
byte[] bytes = db2.Treasures.FirstOrDefault(au => au.treasureID == item.treasureID).itemImage;
string imageBase = Convert.ToBase64String(bytes);
imageSource = string.Format("data:image/gif;base64,{0}", imageBase);
<img id="#item.treasureID" src="#imageSource"/>
}
}
}
}
This calls the DB and gets a list of Learner_Treasure objects which you use to output on view. Server side code gets executed once every page request, this is exactly what is happening. It will not asynchronously update without a request to the server.
You need to implement an ajax request to pull the latest Learner_Treasure list into the view. Again this comes down to the first side note I gave, the reason is because you are mixing your dbcontext with your view and expecting it to update on the fly. If you implement a layer which serves your view with the data (controller), you could call this asynchronously and have the page update without it reloading.
For instance you could write a call in your controller to get a single LearnerTreasure item in json.
[HttpGet]
public ActionResult GetLearnerTreasureItem(int Id)
{
using (The_Factory_Chante.Models.The_FactoryDBContext db2 = new The_Factory_Chante.Models.The_FactoryDBContext()) {
learnerTreasureItem = db2.Learner_Treasure.FirstOrDefault(x => x.Id == Id);
return Json(new { image = Convert.ToBase64String(learnerTreasureItem.itemImage), treasureId = learnerTreasureItem.TreasureID }, JsonRequestBehavior.AllowGet);
}
}
And then call it with ajax in your view, like you did with the update.
$.ajax({
cache: false,
type: "GET",
url: '/YOURCONTROLLERNAME/GetLearnerTreasureItem?id=1',
contentType: 'application/json',
dataType: "json",
success: function (data) {
//build image element
var image = '<img id="' + data.treasureId + '" src="data:image/jpg;base64,' + data.image + '"';
//add the image to where you need it.
$(image).appendTo("body");
},
error: function (xhr) {
alert("Error occurred while loading the image.");
}
});
I hope this helps.

Update in treasures images list
<img id="#item.treasureID" src="#imageSource" onclick="return MakeSure(this, #item.treasureID)" />
read that param in MakeSure method. also I just assume Learner_Treasure images listed in ul named 'ulLearnerTreasure'.
function MakeSure(sender,treshID) {
var id = treshID;
var imgSrc = $(sender).attr("src");
$.ajax({
url: "../../WebService.asmx/MakeSure",
data: "{ 'id': '" + id + "'}",
dataType: "json",
type: "POST",
contentType: "application/json; charset=utf-8",
success: function (data) {
var li = '<li><img id ="'+ treshID +'"src="'+ imgSrc +'" /></li>';
$("#ulLearnerTreasure").append(li);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
}
});
};

I would implement it using HtmlHelpers, like so: (as someone suggested, using db code directly is not a good practice, you need to change that.)
public static class HTMLHelpers
{
public static IHtmlString TreasureImages(this HtmlHelper helper, List<The_Factory_Chante.Models.Learner_Treasure> lern)
{
StringBuilder sb = new StringBuilder();
using (The_Factory_Chante.Models.The_FactoryDBContext db2 = new The_Factory_Chante.Models.The_FactoryDBContext())
{
string imageSource = "";
lern = db2.Learner_Treasure.ToList();
if (lern != null)
{
foreach (var item in lern)
{
if (item.learnerID == UserInfo.ID)
{
byte[] bytes = db2.Treasures.FirstOrDefault(au => au.treasureID == item.treasureID).itemImage;
string imageBase = Convert.ToBase64String(bytes);
imageSource = string.Format("data:image/gif;base64,{0}", imageBase);
sb.Append("<li><img id='#item.treasureID' src='#imageSource'/></li>");
}
}
}
}
return new HtmlString(sb.ToString());
}
}
Placeholder for your images:
<ul id="TreaureImagesSection">
</ul>
In your cshtml page, load the list with this script, the first time or whenever you need the updated list
<script>
$.ajax({
cache: false,
type: "GET",
url: '/YOURCONTROLLER/TreasuresList',
contentType: 'application/json; charset=utf-8',
success: function (data) { // the data returned is List<The_Factory_Chante.Models.Learner_Treasure>
$("#TreaureImagesSection").html('#Html.TreasureImages(data)');
},
error: function (xhr) {
alert("Error occurred while loading the image.");
}
});
</script>

Related

Posting AJAX string to MVC Controller

I am trying to post a string (the name of the href the user clicked on) using AJAX to my MVC controller (which it will then use to filter my table results according to the string).
Whilst I have managed to get it to post (at-least according to the alerts) on the AJAX side, it doesn't seem to arrive properly on the controller side and is seen as null in my quick error capture (the if statement).
Please excuse the useless naming conventions for the moment. I've been going through countless methods to try and fix this, so will name properly when I've got a proper solution :).
I've been at work for this for a long while now and can't seem to solve the conundrum so any help is appreciated please! I'm very new to AJAX and MVC in general so I'm hoping it's a minor mistake. :) (FYI I have tried both post and get and both seem to yield the same result?)
Controller:
[Authorize]
[HttpGet]
public ActionResult GetSafeItems(string yarp)
{
using (CBREntities2 dc = new CBREntities2())
{
if (yarp == null)
{
ViewBag.safeselected = yarp;
}
var safeItem = dc.Items.Where(a => a.Safe_ID == yarp).Select(s => new {
Serial_Number = s.Serial_Number,
Safe_ID = s.Safe_ID,
Date_of_Entry = s.Date_of_Entry,
Title_subject = s.Title_subject,
Document_Type = s.Document_Type,
Sender_of_Originator = s.Sender_of_Originator,
Reference_Number = s.Reference_Number,
Protective_Marking = s.Protective_Marking,
Number_recieved_produced = s.Number_recieved_produced,
copy_number = s.copy_number,
Status = s.Status,
Same_day_Loan = s.Same_day_Loan
}).ToList();
// var safeItems = dc.Items.Where(a => a.Safe_ID).Select(s => new { Safe_ID = s.Safe_ID, Department_ID = s.Department_ID, User_ID = s.User_ID }).ToList();
return Json(new { data = safeItem }, JsonRequestBehavior.AllowGet);
}
}
AJAX function (on View page):
$('.tablecontainer').on('click', 'a.safeLink', function (e) {
e.preventDefault();
var yarp = $(this).attr('safesel');
var selectedSafeZZ = JSON.stringify("SEC-1000");
$.ajax({
url: '/Home/GetSafeItems',
data: { 'yarp': JSON.stringify(yarp) },
type: "GET",
success: function (data) {
alert(yarp);
console.log("We WIN " + data)
},
error: function (xhr) {
alert("Boohooo");
}
});
})
** The Alert reveals the correct type: "SEC-1000"
But the console Log shows: WE WIN [Object object]??
I have tried something basic in a new mvc dummy project :
View page basic textbox and a button :
<input type="text" id="txt_test" value="test"/>
<button type="button" class="btn" onclick="test()">Test</button>
<script type="text/javascript">
function test()
{
var text = $("#txt_test")[0].value;
$.ajax({
url: '#Url.RouteUrl(new{ action="GetSafeItems", controller="Home"})',
// edit
// data: {yarp: JSON.stringify(text)},
data: {yarp: text},
type: 'GET',
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: function(data) {
// edit
// alert(JSON.stringify(data));
alert(data.data);
}});
}
</script>
Controller :
[HttpGet]
public ActionResult GetSafeItems(string yarp)
{
return Json(new {data = string.Format("Back end return : {0}",yarp)}
, JsonRequestBehavior.AllowGet);
}
Alert result => {"data":"Back end return : \"test\""}
It's a simple ajax call to a web method. You don't return a view, so I don't understand the use of
if (yarp == null)
{
ViewBag.safeselected = yarp;
}
Also I see an [Authorize] attribute, you perhaps use some authentication and I don't see any authentication header on your ajax call
Try this:
$.each(data, function (i) { console.log("We WIN " + data[i].Serial_Number )});

I can not display data into input Text

I am receiving Json data via Ajax but the problem is that I cannot display data into input Text and every things work fine any one can help please
<script type="text/javascript">
function getProblemById(Id) {
var Id = Id;
$.ajax({
url: "/BarnoProblems/getById?Id=" + Id,
type: "GET",
dataType: "json",
success: function (data) {
$('#Discrptions').val( data.Discrption);//here is the problem
},
error: function () {
alert("erorr");
}
});
}
</script>
this is my C# and it is work fine
public JsonResult getById(int Id){
var pro = from pr in db.BarnoProblems
join br in db.Branches
on pr.BranchId equals br.Id
where pr.Id == Id
select new
{
pr.Id,
pr.Discrption,
pr.ProblemImage,
pr.ProblemType,
pr.Source,
pr.statute,
pr.comment,
barnchname = br.Name,
citys = pr.Branch.City.Name
};
return Json(pro.ToList(), JsonRequestBehavior.AllowGet);
}
Try this:
success: function(data){
if(data.length > 0)
$('#Discrptions').val(data[0].Discrption);
}
Without seeing all your code, I'm assuming the thing you are hung up on is the way you are processing the data. It should look like this:
data['Discrption']

How to pass multipart/form-data to c# method via Ajax

I am using html2canvs.js for taking screen shots of the page which is described here:
How to take screen shot of current webpage using javascript/jquery
The above process works fine, but now I want to pass the Base64 data to a c# method via ajax. My code looks like:
$('#gbox_Basic').html2canvas({
onrendered: function (canvas) {
var imgString = canvas.toDataURL("image/png");
$.ajax({
type: "POST",
url: "/Home/SentEmail2",
data: //how to pass base64 data 'imgString' ,
contentType: "multipart/form-data",
success: function () {
}
});
}
});
And here is my c# method
public void SentEmail2(what type of param it would accept?) {
//process incoming params
}
Give a try to this:
Controller.cs
[HttpPost]
public ActionResult Index(HttpPostedFileBase file) {
if (file.ContentLength > 0) {
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
file.SaveAs(path);
}
return RedirectToAction("Index");
}
Form
The object FormData will hold the file element to be send.
var formData = new FormData($('form')[0]);
$.ajax({
url: '/Home/SentEmail2', //Server script to process data
type: 'POST',
xhr: function() { // Custom XMLHttpRequest
var myXhr = $.ajaxSettings.xhr();
if(myXhr.upload){ // Check if upload property exists
myXhr.upload.addEventListener('progress',progressHandlingFunction, false); // For handling the progress of the upload
}
return myXhr;
},
//Ajax events
beforeSend: beforeSendHandler,
success: completeHandler,
error: errorHandler,
// Form data
data: formData,
//Options to tell jQuery not to process data or worry about content-type.
cache: false,
contentType: false,
processData: false
});
References:
http://www.dustinhorne.com/post/2011/11/16/AJAX-File-Uploads-with-jQuery-and-MVC-3
http://haacked.com/archive/2010/07/16/uploading-files-with-aspnetmvc.aspx/

json Array posting to mvc controller

I want to post JSON array to MVC controller through AJAX POST as:
$.ajax({
type: 'POST',
data: json.stringify(totaldata),
traditional:true,
url: '/Builder/Save',
success: function () {
alert("Playlist saved successfully!!");
}
})
and my controller code is have made array of one ViewModel & want to update those values as.
[HttpPost]
public ActionResult Save(IList<ItemEditViewModel> data,long playlistid=0, string Title="")
{
for (int i = 0; i < data.Count; i++)
{
var pc = db.PlaylistContents.FirstOrDefault(x => x.PlaylistContentId == data[i].ID);
if (pc == null)
{
pc = new PlaylistContent();
db.PlaylistContents.Add(pc);
}
pc.ContentMetaDataId = data[i].MetaID;
pc.PlaylistContentSequenceId = i + 1;
}
db.SaveChanges();
return RedirectToAction("Playlist", new {ID=playlistid });
}
But the Object is set to null in Controller.
My ViewModel is as,
public class ItemViewModel
{
public long ID{get;set;}
public long MetaID{get;set;}
}
Try adding the content type in ajax call,
contentType : 'application/json',
By default ajax sends with content type application/x-www-form-urlencoded; charset=UTF-8
Edit
also i dont know it this is a typo, json.stringify should be JSON.stringify
hope this helps.
$.ajax({
type: 'POST',
data: {"data":json.stringify(totaldata)},//You missed the format
traditional:true,
url: '/Builder/Save',
success: function () {
alert("Playlist saved successfully!!");
}
})
The Problem is solved & my application is working now properly.
I have just done JSON.stringify() on array elements & not the whole ajax data for posting.
the code is as written below:
var totaldata = { data: data, playlistid: parseInt(playlistid), Title: Title };
$.ajax({
type: 'POST',
data: { data: JSON.stringify(data), playlistid: parseInt(playlistid), Title: Title, deleted: JSON.stringify(deleted) },
traditional:true,
url: 'Save',
success: function (data) {
alert("Playlist saved successfully!!");
}
})

JSON TinyMCE return value "\t"

Should I use another variable for "streszczenie"? or what should I do?
In my opinion in TinyMCE body have html but I get only "\t" Pobably I have got problem with JS
this is new problem - this question is related with this link. I added this for other users
this I write in TinyMCE
this I get from TinyMCE textarea "streszczenie"
As you can see there is text ghhfgh but I can`t get this text
Now I have got problem with execute JSON
<script type="text/javascript">
function Save() {
tinyMCE.triggerSave();
var Temat_controll = $('#Temat').val();
var Streszczenie_controll = tinyMCE.get('Streszczenie').getContent();
var PelnyOpis_controll = $('#PelnyOpis').text();
$.ajax({
url: '#Url.Action("DodajTematSave", "StronaGlowna")',
dataType: "json",
data: {
Temat: Temat_controll,
Streszczenie: Streszczenie_controll,
PelnyOpis: PelnyOpis_controll
},
type: "POST",
async: false,
error: function() {
},
success: function(data) {
if (data.Success) {
alert('success');
}
}
});
}
</script>
I get this but all the time JSON is not execute
When I click button tinyMCE.get('Streszczenie').getContent() is empty I check this and I don`t know why because I have got text into textarea
<script type="text/javascript">
function Save() {
var Temat_controll = $('#Temat').val();
var $d = tinyMCE.get('Streszczenie').getContent();
if ($d.length != 0) {
if ($d.val().length != 0) {
var Streszczenie_controll = tinyMCE.get('Streszczenie').getContent();
}
else {
var Streszczenie_controll = 'ewewe';
}
}
var PelnyOpis_controll = $('#PelnyOpis').text();
$.ajax({
url: '#Url.Action("DodajTematSave", "StronaGlowna")',
dataType: "json",
data: {
Temat: Temat_controll,
Streszczenie: Streszczenie_controll,
PelnyOpis: PelnyOpis_controll
},
type: "POST",
async: false,
error: function () {
},
success: function (data) {
if (data.Success) {
alert('success');
}
}
});
}
</script>
You are getting the content in wrong way, not by jQuery's val().
To get the tinymce content, just use tinyMCE object reference:
// Get the HTML contents of the currently active editor
console.debug(tinyMCE.activeEditor.getContent());
// Get the raw contents of the currently active editor
tinyMCE.activeEditor.getContent({format : 'raw'});
// Get content of a specific editor:
tinyMCE.get('content id').getContent()
As mentioned:
http://www.tinymce.com/wiki.php/API3:method.tinymce.Editor.getContent
Hope it heled. Polish man : )

Categories