On a button click, I want to call a Controller method in which I create a PNG image dynamically. I want to then send that image to the view and display it for the user to see. I can't quite figure out how to properly do this, or what I'm exactly doing wrong. My code is as follows:
View
<div style="height:350px; margin:10px;">
<img id="rsDiagram" src="" alt="RS Diagram" class="partDiagram">
</div>
Controller
public ActionResult RSView(string orderNumber)
{
// I create the png and save it to wwwroot/images/
string outfile = Path.GetFullPath(Path.Combine(_hostingEnvironment.WebRootPath, "images", "RSView.png"));
string fileToSend = Convert.ToBase64String(System.IO.File.ReadAllBytes(outfile));
return Json(fileToSend);
}
Javascript
//This is called on a button click
$.ajax({
type: "GET",
url: "/Home/RSView",
data: { "orderNumber": $("#shopOrderNumber").val() },
success: function (response) {
rs.style.display = "block";
$("rsDiagram").attr("src", "data:image/png;base64," + response + '"');
},
error: function (response) {
alert(response.responseText);
}
});
Seems your code is almost alright only little problem founded how you are binding the response on your image tag. Just replace the below line with your older one.
$("#rsDiagram").attr('src', 'data:image/png;base64,' + response);
Note: I have tried to keep all of your existing code.
So the full solution would be looks like
Controller:
Same as yours
public ActionResult RSView()
{
// I create the png and save it to wwwroot/images/
string outfile = Path.GetFullPath(Path.Combine(_hostEnvironment.WebRootPath, "images", "RSView.png"));
string fileToSend = Convert.ToBase64String(System.IO.File.ReadAllBytes(outfile));
return Json(fileToSend);
}
View:
Also same, I just added a button so that anyone can test with this solution
<div style="height:350px; margin:10px;">
<img id="rsDiagram" src="" class="partDiagram">
</div>
<!-- Button for calling ajax request -->
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
Load Images
</button>
Javascript:
#section scripts {
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<script>
$(document).ready(function () {
$("button").click(function (e) {
$.ajax({
type: "GET",
url: "/Home/RSView",
//data: { "orderNumber": $("#shopOrderNumber").val() },
success: function (response) {
console.log(response);
$("#rsDiagram").attr('src', 'data:image/png;base64,' + response);
},
error: function (response) {
alert(response.responseText);
}
});
});
});
</script>
}
Note: Here in ajax request I have commented your parameter { "orderNumber": $("#shopOrderNumber").val() as I am calling the
controller for the predefined image so that I didn't sent any parameter. Hope you get me here.
Output:
Hope it would resolve your problem.
Related
I have the following HTML code in my page model
<div class="container-fluid">
<div class="row" id="tableToChange">
#Html.Partial("DeliveryDetails")
</div>
</div>
And the following Ajax call which returns an 404 error when clicking on the load button.
$(function () {
$('#load').on('click', function () {
$.ajax({
type: 'POST',
url: '#Url.Action("GetDeliveryDetails", "DeliveryController", null)',
success: function (data) {
$('#tableToChange').html(data);
console.log("Success call");
}
});
console.log("Success click");
});
});
The URL seems fine as it returns the following path: 'DeliveryController/GetDeliveryDetails'.
Probably worth noting that the following address doesn't return anything as well:
https://localhost:5001/Customer/DeliveryController/GetDeliveryDetails
The DeliveryController is as follows:
public ActionResult GetDeliveryDetails()
{
Debug.WriteLine("Called the controller!");
return View("DeliveryDetailsView");
}
and is located in the same folder as the main page model (Customer/Delivery.cshtml)
I'm having some issues with updating a partial view in my index view. Basically, based on a click, I would like to have updated information.
//controller
public ActionResult Index()
{
var filteredObservations = getFilteredObservationSessions().ToList();
var observationManagementVm = new ObservationManagementVM(filteredObservations);
return View(observationManagementVm);
}
public ActionResult indexPagedSummaries(int? page, List<ObservationSessionModel> data)
{
var alreadyFilteredObservations = data;
int PageSize = 10;
int PageNumber = (page ?? 1);
return PartialView(alreadyFilteredObservations.ToPagedList(PageNumber, PageSize));
}
My main view
//index.cshtml
#model AF.Web.ViewModels.ObservationManagementVM
....
<div id="testsim">
#Html.Action("indexPagedSummaries", new { data = Model.ObservationSessions })
</div>
<input id="new-view" value="Sessions" type="button" />
<script>
$("#new-view").click(function() {
$.ajax({
type: "GET",
data: { data: "#Model.FeedBackSessions" },
url: '#Url.Action("indexPagedSummaries")',
cache: false,
async: true,
success: function (result) {
console.log(result);
$('#testsim').html(result);
$('#testsim').show();
}
});
});
</script>
....
And my partial view
//indexPagedSummaries.cshtml
#model PagedList.IPagedList<AF.Services.Observations.ObservationSessionModel>
#using (Html.BeginForm("indexPagedSummaries"))
{
<ol class="vList vList_md js-filterItems">
#foreach (var item in Model)
{
#Html.DisplayFor(modelItem => item)
}
</ol>
<div>
Page #(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of #Model.PageCount
#Html.PagedListPager(Model, page => Url.Action("Index",
new { page }))
</div>
}
Html.Action() returns what I want perfectly, but it doesn't seem to be able to be triggered by a button click.
So, I'm not getting any errors, but the url doesn't give any data back. When I try to run the Observation/indexPagedSummary url without passing in data, I get a System.ArgumentNullException error, so I'm assuming that something is being transferred to the view model. Any help would be so appreciated.
Have not run your code but I believe it is because you are not sending the data along with the #Url.Action
Main View:
//index.cshtml
#model AF.Web.ViewModels.ObservationManagementVM
....
<div id="testsim">
#Html.Action("indexPagedSummaries", new { data = Model.ObservationSessions })
</div>
<input id="new-view" value="Sessions" type="button" />
<script>
$("#new-view").click(function() {
$.ajax({
type: "GET",
data: { data: "#Model.FeedBackSessions" },
url: '#Url.Action("indexPagedSummaries", "[Controller Name]", new { data = Model.ObservationSessions})',
cache: false,
async: true,
success: function (result) {
console.log(result);
$('#testsim').html(result);
$('#testsim').show();
}
});
});
</script>
If that doesn't help I have had issues when I have had a content-type mismatch or a datatype mismatch. You may need to add those to you ajax request.
Change your ajax data line to this:
data: { data: JSON.stringify(#Model.FeedBackSessions) },
You may also need to add these lines to the ajax:
dataType: 'json',
contentType: 'application/json; charset=utf-8',
You can see in one of your comments above that the current URL is being formed with a description of the List Object, rather than the contents of it:
http://localhost:60985/Observation/indexPagedSummaries?data=System.Collections.Generic.List%601%5BAF.Services.Observations.ObservationSessionModel%5D&data=System.Collections.Generic.List%601%5BAF.Services.Observations.ObservationSessionModel%5D&_=1482453264080
I'm not sure if there's a better way, but you may even have to manually get the model data into Javascript before posting it.
eg:
<script>
var temp = [];
#foreach (var item in Model.FeedBackSessions){
#:temp.push(#item);
}
</script>
and then data: { data: JSON.stringify(temp) },
I'm not well versed in this framework so I need some help here. In a view I want to add a link or a button on clicking which a certain file gets deleted from the server.
I've added this method to the controller:
[Authorize]
public ActionResult DeleteFile(string path)
{
if ((System.IO.File.Exists(path)))
{
try
{
System.IO.File.Delete(path);
}catch(Exception ex)
{
Debug.WriteLine("Deletion of file failed: " + ex.Message);
}
}
return View();
}
Seemed straightforward, though I'm not sure about the return View();. Now in the view, I need a form, because the path to the file that should be deleted needs to be posted to the controller, is that correct? This is what I got so far, mimicked from other code in the project:
#Html.BeginForm("DeleteFile", "Home", FormMethod.Post, new { id = "delete-attachment-form" })
{
#Html.Hidden("path", path)
}
path is a JavaScript variable containing the server path to the file that needs to be deleted. If I'm on the right track here, how do I add a button or a link to click on that will send the form?
Should just be able to add a submit button:
<input type="submit" name="submit" />
You should have a form and a button like this
#Html.BeginForm("Controller", "DeleteFile", new {Path= filePath},FormMethod.Post)
{
//Button
}
Or using Ajax and Jquery
var values = $(this).serialize();
$.ajax({
type: 'POST',
url: "url?path="+path.tostring(),
data: values ,
success: function(response) { //update view }
});
Inside your form you can add a button and then handle the button click in JavaScript.
#Html.BeginForm("DeleteFile", "Home", FormMethod.Post, new { id = "delete-attachment-form" })
{
#Html.Hidden("path", path)
<button id="delete-btn" type="button" class="btn btn-danger">
Delete
</button>
}
Then the <script type="text/javascript"> block:
$(function () {
$('#delete-btn').click(function () {
var query = $('#delete-attachment-form');
var form = query[0];
var toPost = query.serialize();
$.ajax({
url: form.action,
type: form.method,
data: toPost,
success: function (result) {
// display result
},
error: function () {
// handle error
}
})
});
});
Also, this is a good tutorial on deleting in ASP.NET MVC
I sometimes have operation that takes a while to compute. I would like to be able to display something, like a kind of grey layer covering everything, or a loading screen, while the operation computes. But I frankly have no idea how to do it.
I'm building an MVC app using MVC4, I'm beginning with jQuery and opened to any suggestions. How might I do that?
EDIT
Here's a sample of page I've been building:
<h2>Load cards</h2>
<script type="text/javascript">
$(document).ready(function () {
$("form").submit(function (event) {
event.preventDefault();
alert("event prevented"); // Code goes here
//display loading
$("#loadingDialog").dialog("open");
alert("dialog opened"); // Never reaches here.
$.ajax({
type: $('#myForm').attr('method'),
url: $('#myForm').attr('action'),
data: $('#myForm').serialize(),
accept: 'application/json',
dataType: "json",
error: function (xhr, status, error) {
//handle error
$("#loadingDialog").dialog("close");
},
success: function (response) {
$("#loadingDialog").dialog("close");
}
});
alert("ajax mode ended");
});
});
</script>
#using (Html.BeginForm())
{
<div class="formStyle">
<div class="defaultBaseStyle bigFontSize">
<label>
Select a Set to import from:
</label>
</div>
<div class="defaultBaseStyle baseFontSize">
Set: #Html.DropDownList("_setName", "--- Select a Set")<br/>
</div>
<div id="buttonField" class="formStyle">
<input type="submit" value="Create List" name="_submitButton" class="createList"/><br/>
</div>
</div>
}
Here's a snippet of code from my javascript file:
$(document).ready(function ()
{
$(".createList").click(function() {
return confirm("The process of creating all the cards takes some time. " +
"Do you wish to proceed?");
});
}
As a bonus (this is not mandatory), I'd like it to be displayed after the user has confirmed, if it is possible. else I do not mind replacing this code.
EDIT
Following Rob's suggestion below, here's my controller method:
[HttpPost]
public JsonResult LoadCards(string _submitButton, string _cardSetName)
{
return Json(true);
}
And here's the "old" ActionResult method:
[HttpPost]
public ActionResult LoadCards(string _submitButton, string _setName)
{
// Do Work
PopulateCardSetDDL();
return View();
}
As of now the code never reaches the Json method. It does enter the ajax method up there (see updated code), but I don't know how to make this work out.
We hide the main content, while displaying an indicator. Then we swap them out after everything is loaded. jsfiddle
HTML
<div>
<div class="wilma">Actual content</div>
<img class="fred" src="http://harpers.org/wp-content/themes/harpers/images/ajax_loader.gif" />
</div>
CSS
.fred {
width:50px;
}
.wilma {
display: none;
}
jQuery
$(document).ready(function () {
$('.fred').fadeOut();
$('.wilma').fadeIn();
});
First you want to have jQuery "intercept" the form post. You will then let jQuery take care of posting the form data using ajax:
$("form").submit(function (event) {
event.preventDefault();
//display loading
$("#loadingDialog").dialog("open");
$.ajax({
type: $('#myForm').attr('method'),
url: $('#myForm').attr('action'),
data: $('#myForm').serialize(),
accept: 'application/json',
dataType: "json",
error: function (xhr, status, error) {
//handle error
$("#loadingDialog").dialog("close");
},
success: function (response) {
$("#loadingDialog").dialog("close");
}
});
});
More information on the $.ajax() method is here: http://api.jquery.com/jQuery.ajax/
You could use the jquery dialog to display your message: http://jqueryui.com/dialog/
There are other ways to display a loading message. It could be as simple as using a div with a loading image (http://www.ajaxload.info/) and some text, then using jQuery to .show() and .hide() the div.
Then, in your controller, just make sure you're returning JsonResult instead of a view. Be sure to mark the Controller action with the [HttpPost] attribute.
[HttpPost]
public JsonResult TestControllerMethod(MyViewModel viewModel)
{
//do work
return Json(true);//this can be an object if you need to return more data
}
You can try creating the view to load the barebones of the page, and then issue an AJAX request to load the page data. This will enable you to show a loading wheel, or alternatively let you render the page in grey, with the main data overwriting that grey page when it comes back.
This is how we do it in our application, however there is probably a better way out there...
if not I'll post some code!
EDIT: Here's the code we use:
Controller Action Method:
[HttpGet]
public ActionResult Details()
{
ViewBag.Title = "Cash Details";
return View();
}
[HttpGet]
public async Task<PartialViewResult> _GetCashDetails()
{
CashClient srv = new CashClient();
var response = await srv.GetCashDetails();
return PartialView("_GetCashDetails", response);
}
Details View:
<div class="tabs">
<ul>
<li>Cash Enquiry</li>
</ul>
<div id="About_CashEnquiryLoading" class="DataCell_Center PaddedTB" #CSS.Hidden>
#Html.Image("ajax-loader.gif", "Loading Wheel", "loadingwheel")
</div>
<div id="About_CashEnquiryData"></div>
<a class="AutoClick" #CSS.Hidden data-ajax="true" data-ajax-method="GET"
data-ajax-mode="replace" data-ajax-update="#About_CashEnquiryData"
data-ajax-loading="#About_CashEnquiryLoading" data-ajax-loading-duration="10"
href="#Url.Action("_GetCashDetails", "Home")"></a>
</div>
Custom Javascript:
$(document).ready(function () {
// Fire any AutoClick items on the page
$('.AutoClick').each(function () {
$(this).click();
});
});
I'm looking for a way to do a "Update Panel" in ASP.NET MVC 3. I found this link: How to make update panel in ASP.NET MVC but didn't work.
So, i did this in my view:
<div>
<input type="text" id="userName" />
<button type="button" onclick="searchUserByName()">Search</button>
</div>
<div id="usersPanel">
#{Html.RenderPartial("_UserList", Model);}
</div>
<script type="text/javascript">
function searchUserByName() {
var userName = $("#userName").val();
$.post('#Url.Action("SearchUserByName")',
{username: userName},
function (htmlPartialView) {
$("#usersPanel").html(htmlPartialView);
}
);
}
</script>
And in my controller:
public ActionResult SearchUserByName(string userName)
{
List<User> users = // code to search users by name
return PartialView("_UserList", users);
}
But i don't know if is a good (or right) way to do that, or if there is a way to do this with asp.net mvc 3. There is a better way to do this, or with asp.net mvc 3?
Just use ajax request to get the results from your action methods. It basically does the same thing as update panels in asp.net.
So something like the following.
$.ajax({
async: false,
cache: false,
type: 'POST',
url: /controller/action,
data: { id: idParam },
beforeSend: function (XMLHttpRequest) {
if (confirmMessage !== undefined) {
return confirm(confirmMessage);
}
return true;
},
success: function (data) {
// do stuff
},
error: function () {
alert('An error occured');
}
});
I would do it like that.
You might also want to take a look at client side libraries for handling bindings etc. Looks like knockoutjs will be included in MVC4
In View:
<script type="text/javascript">
var userName = $("#userName").val();
$.ajax({
url: "/<ControolerName>/SearchUserByName",
type: "POST",
data: { userName: userName},
success: function (result) {
$('#divResults').html(result);
},
error: function (ex) {
alert("Error");
}
<script>
<div id="divResults">
</div>
In controller:
public PartialViewResult SearchUserByName(string userName)
{
List<User> users = // code to search users by name
return PartialView("_users", users);
}