FileUploader Asp mvc Telerik Asynchrounous Content - javascript

I tried to Use the Telerik component Upload in asp mvc .
#(Html.Telerik().Upload()
.Name("attachement")
.Multiple(true)
.Async(async => async
.Save("Save", "Image")
.Remove("Remove", "Image")
.AutoUpload(true)
).ClientEvents(events => events.OnSuccess("onSuccess")))
In My Controller I have:
public ActionResult Save(HttpPostedFileBase attachement)
{
var fileName = attachement.FileName;
Guid id = SaveImage(attachement);
return Json(
new
{
Succces = true,
Content=id,
}
);
}
In my View I need to display the content of the Json Result ,
I have a event on the uploader called OnSucces
function onSuccess(e) {
}
How Can I get the JsonContent in this method javascript and display the content .
Or all this logic is wrong .
Thanks in advance

Check the sending and receiving metadata help article.

Related

.net core mvc get controller method return the downloading file , but not working?

I have List<model> and I convert to JSON in Javascript and when I click button call controller method
and pass paramater like this :
$('#exceldownload').click(function(){
var json = #Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.ReportListModel,Newtonsoft.Json.Formatting.Indented));
json = JSON.stringify(json);
window.location = "#Url.Action("ReportExcel","Report")?model="+json+"";
});
And Controller Code :
public FileResult ReportExcel(string model)
{
var b = JsonConvert.DeserializeObject<List<ReportListModel>>(model);
if (b.Count == 0)
{
return File(Encoding.UTF8.GetBytes("empty"), "text/plain", "empty");
}
else
{
DataTable table = (DataTable)JsonConvert.DeserializeObject(JsonConvert.SerializeObject(b), (typeof(DataTable)));
using (var excelPack = new ExcelPackage())
{
var ws = excelPack.Workbook.Worksheets.Add("WriteTest");
ws.Cells.LoadFromDataTable(table, true, OfficeOpenXml.Table.TableStyles.Light8);
var FileBytesArray = excelPack.GetAsByteArray();
return File(FileBytesArray, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "test.xlsx");
}
}
}
But when I click button and getting like this :
This site can't be reached,
Localhost refused to connect,
ERR_CONNECTION_CLOSED
I want to when I click button download excel file.
It's crashing at this line:
window.location = "#Url.Action("ReportExcel","Report")?model="+json+"";
Change it to
window.location = #Url.Action("ReportExcel","Report") + "?model="+json+"";
Try debugging the ASP.NET code. Probably an internal server error occurs.

Cannot delete file because it is being used by another process, ASP.NET Core MVC

I am using ASP.Net Core with MVC for creating an app. I am using visual studio and IIS express currently.
Below is my current project structure:
*project directory
-wwwroot
-areas
-attachments
-controllers
-models
-views
I currently store images inside the attachments folder.
Previously I have written something like that inside my startup.cs
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), "Attachments")),
RequestPath = "/Attachments"
});
I have also done something like this below:
appendImage(#Url.Content("~/Attachments/")+result.fileName);
I did this to display an image on my view. The image is displayed successfully.
What I am trying to achieve now is the on the UI allow the user to make a choice to delete the files inside that attachments folder
I tried the following code:
string contentRootPath = _hostingEnvironment.ContentRootPath;
string fullImagePath = Path.Combine(contentRootPath + "\\Attachments", currentItemToDelete.FileName);
if (System.IO.File.Exists(fullImagePath))
{
try{
System.IO.File.Delete(fullImagePath);
}catch(Exception e){
operationResult = "Attachment Path. Internal Server Error";
}
}
The execution does enter the if (System.IO.File.Exists(fullImagePath))
but it raises an exception when it reaches System.IO.File.Delete. The exception states that the file which resides in that path is being used by another process. And thus I cannot delete the file. The only process that is accessing the file is the web app I am creating/debugging at the same time. How do I prevent this exception from happening? Do I have to use other kind of code to delete the file ?
EDIT to include more details:
Inside my view(index.cshtml):
appendImage is a javascript function:
function appendImage(imgSrc) {
var imgElement = document.createElement("img");
imgElement.setAttribute('src', imgSrc);
if (imgSrc.includes(null)) {
imgElement.setAttribute('alt', '');
}
imgElement.setAttribute('id', "img-id");
var imgdiv = document.getElementById("div-for-image");
imgdiv.appendChild(imgElement);
}
That function is called below:
$.ajax({
url:'#Url.Action("GetDataForOneItem", "Item")',
type: "GET",
data: { id: rowData.id },
success: function (result) {
removeImage();
appendImage(#Url.Content("~/Attachments/")+result.fileName);
$("#edit-btn").attr("href", '/Item/EditItem?id=' + result.id);
},
error: function (xhr, status, error) {
}
});
After calling appendImage(); I change the href of a <a> tag. When the user clicks on the link, the user is directed to another page(edit.cshtml). In the page, the image which resides in that path is also being displayed with code like this:
<img src="#Url.Content("~/Attachments/"+Model.FileName)" alt="item image" />
In this new page(edit.cshtml), there is a delete button. Upon clicking the delete button, the execution of the program goes to the controller which is this controller function:
[HttpPost]
public string DeleteOneItem(int id)
{
//query the database to check if there is image for this item.
var currentItemToDelete = GetItemFromDBDateFormatted(id);
if (!string.IsNullOrEmpty(currentItemToDelete.FileName))
{
//delete the image from disk.
string contentRootPath = _hostingEnvironment.ContentRootPath;
string fullImagePath = Path.Combine(contentRootPath + "\\Attachments", currentItemToDelete.FileName);
if (System.IO.File.Exists(fullImagePath))
{
try
{
System.IO.File.Delete(fullImagePath);
}catch(Exception e)
{
}
}
}
return "";
}
EDIT to answer question:
Add in
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
before system.io.file.delete
you can replace your C# method DeleteOneItem with this given code. may be it might work.
[HttpPost]
public string DeleteOneItem(int id)
{
//query the database to check if there is image for this item.
var currentItemToDelete = GetItemFromDBDateFormatted(id);
if (!string.IsNullOrEmpty(currentItemToDelete.FileName))
{
//delete the image from disk.
string contentRootPath = _hostingEnvironment.ContentRootPath;
string fullImagePath = Path.Combine(contentRootPath + "\\Attachments", currentItemToDelete.FileName);
if (System.IO.File.Exists(fullImagePath))
{
try
{
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
System.IO.File.Delete(fullImagePath);
}
catch (Exception e) { }
}
}
return "";
}
try
{
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
System.IO.File.Delete(fullImagePath);
}
catch(Exception e){
}

unable to dynamically get the filename from spring controller to the html page to load the newly created file

I want to load the PDF file dynamically and show on browser. PDF file is created on the fly when user clicks on button and the filename has timestamp in it. So i cannot give the PDF filename in the html code as shown below as it changes based on the timestamp(PDF file name is given along with the timestamp when it was created as shown in below spring controller).
Below is the code.
html code:
<div ng-controller="generatePDFController">
<button ng-click="generatePDF()">Re-Generate PDF</button>
<object data="C:/allFiles/PDFFiles/spreadDetails.pdf" type="application/pdf" width="100%" height="100%">
<iframe src="C:/allFiles/PDFFiles/spreadDetails.pdf" width="100%" height="100%" style="border: none;">
This browser does not support PDFs.
Download PDF
</iframe>
</object>
</div>
js code:
app.controller('generatePDFController', function($scope, MyService) {
$scope.generatePDF = function() {
MyService.createPDF().then(
function(response) {
$scope.pdf = response;
},
function(errResponse) {
});
}
});
//service call
_myService.createPDF = function() {
var deferred = $q.defer();
var repUrl = sURL + '/allDataGeneration/generatePDF.form';
$http.get(repUrl)
.then(
function(response) {
deferred.resolve(response.data);
},
function(errResponse) {});
return deferred.promise;
}
spring controller:
#RequestMapping(value = "/generatePDF", method = RequestMethod.GET)
public# ResponseBody List < MyDTO > generatePDF() {
List < MyDTO > response = service.getAllData();
//create PDF and write the response in it
createPDFFile(response);
return response;
}
void createPDFFile(List < MyDTO > res) {
String FILE_PATH = "C:\\allFiles\\PDFFiles\\spreadDetails";
String FILE_EXTENSION = "pdf";
DateFormat df = new SimpleDateFormat("MM-dd-yyyy hh-mm-ssa");
String filename = null;
try {
filename = FILE_PATH + df.format(new Date()) + "." + FILE_EXTENSION;
} catch (Exception e) {
e.printStackTrace();
}
File file = new File(filename);
System.out.println("-----filename------------ " + filename); //PDF file is created successfully
//spreadDetails07-13-2017 02-59-51PM ,when user clicks on GeneratePDF in UI, it hits this controller and generates the PDF
//logic to write the data inside PDF file
}
The above shown code is the complete flow of my sample application. Now when user clicks on Re-Generate PDF button, it comes to above mentioned spring controller creates a file with timestamp and writes the data in it.How to pass the newly created pdf filename to the html code <object data="C:/allFiles/PDFFiles/spreadDetails.pdf" .. so that when pdf file is created it dynamically loads and show on UI.
---EDITED---
Please see the above edited code. createPDF(List<MyDTO>) is a new method in which i'm creating a pdf file and writing the content. I will be reusing this method.
Try to follow these steps :
Change the signature of the Java method generatePDF() in order to return a String representing the name of your file. This gives you the possibility to pass the name of the file to your JavaScript ;
In your controller, do $scope.pdfName = response. This way the name of the file is store the variable $scope.pdfName ;
Last step, replace <object data="C:/allFiles/PDFFiles/spreadDetails.pdf" ...> by <object data="{$scope.pdfName}" ...>
This should work.
Marine
EDIT given your own edit :
Your method generatePdf() is incorrect : you wrote that it must return a List<MyDto> but the keyword return is nowhere.
Do you really need to return he object List<MyDto> ? In any case, you need to return the name of the file to be able to use it in your JavaScript. So, you have two solutions : either this method only returns a String representing the name of the PDF, or it returns an object with two fields, one String and one List<MyDto>. In this second cas, you will need to do
$scope.pdfName = response.fieldContainingTheNameOfTheFile.

Page is not refreshed by calling RedirectToAction

In the View I have a linked button and there is java scripts to collect information from view and then post to the corresponding action 'GroupDeny'
#Html.ActionLink("Deny Selected", "GroupDeny", null, new { #class = "denySelectedLink" })
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript">
$(document).on('click', '.denySelectedLink', function (e) {
//Cancel original submission
e.preventDefault();
var identifiers = new Array();
//build the identifiers . . .
var jsonArg = JSON.stringify(identifiers);
$.post('/LicenseAssignment/GroupDeny?licensePermissionIdentifiers=' + encodeURIComponent(jsonArg));
});
</script>
Then in the controller, the GroupDeny will update the DB and then
call RedirecToAction in order to refresh the view
public class LicenseAssignmentController : Controller
{
[HttpPost]
public ActionResult GroupDeny(string licensePermissionIdentifiers)
{
// changes the DB
return RedirectToAction("Index");
}
// GET:
public async Task<ActionResult> Index()
{
var model = get data from DB
return View(model);
}
Everything seems work as expected, The Index will be called after the RedirectToAction("Index") is executed, and the model is update to date their when I watch it during debugging, the only problem is that the page is not refreshed at all, that is to say the view still keep unchanged, but after I refresh the page manually (press F5), the data will be updated with the values from DB
We use AJAX when we don't want to navigate away from the page. Your $.post() is an AJAX request.
Since you want navigation add a form to your page
#using(Html.BeginForm("GroupDeny", "LicenseAssignment", FormMethod.Post))
{
<input type="hidden" value=""
name="licensePermissionIdentifiers"
id="licensePermissionIdentifiers" />
}
Now submitting this form will navigate
$(document).on('click', '.denySelectedLink', function (e) {
e.preventDefault(); // prevent link navigation
var identifiers = new Array();
//build the identifiers . .
// populate the form values
$("#licensePermissionIdentifiers").val(identifiers);
$("form").submit();
});
The RedirectToAction() returns to the browser a 302 Redirect to LicenseAssignment/Index then you hit the Index action.
Since you are using Ajax you will have to redirect on the return of your $.post call and change your GroupDeny to a JsonResult.
Something like this maybe:
JS
$.post('/LicenseAssignment/GroupDeny?licensePermissionIdentifiers=' + encodeURIComponent(jsonArg), function(data){
if(data.Success){
//redirect
window.location.reload();
}else{
//handle error
}
});
Controller Action
[HttpPost]
public JsonResult GroupDeny(string licensePermissionIdentifiers)
{
// changes the DB
return Json(new { Success = true });
}

Inject something to ASP MVC Result

In my project I need to add functionality, that show infobox in right top corner of page, when client save something. Everything works fine when save operation do redirect to another page in my solution.
Client run save action:
[SaveAction] //my own action filter to show info box
public ActionResult Details(int id, FormCollection form)
{
var pojazd = PojazdRepo.GetById(id);;
if (UpdateAndSave(pojazd, form))
{
return RedirectToAction("Index");
}
else
{
return View(GetDetailsViewModel(id, true));
}
}
Now my action filter test that ModelState.IsValid is true then add something to TempData:
public class SaveActionAttribute : ActionFilterAttribute
{
private bool test;
private bool isAjax;
public override void OnActionExecuted(ActionExecutedContext ctx)
{
test = ctx.Controller.ViewData.ModelState.IsValid;
isAjax = ctx.HttpContext.Request.IsAjaxRequest();
base.OnActionExecuted(ctx);
}
public override void OnResultExecuting(ResultExecutingContext ctx)
{
if (test)
{
if (isAjax) ctx.Controller.TempData["ActionPopUp"] = "";
else ctx.Controller.TempData["ActionPopUp"] = "save";
}
base.OnResultExecuting(ctx);
}
}
And my Site.Master run script if TempData["ActionPopUp"] = "save":
<script type="text/javascript">
$(document).ready(function () {
var test = '<%: TempData["ActionPopUp"] %>';
if (test != '') SaveSuccessPopUp(test);
});
</script>
As mentioned, this solution works fine, when controller make Redirect and Site.Master is loaded again, my problem is, how to inject SaveSuccessPopUp() function to action result, when Action was called by AJAX and return something, what don't reload page and don't run Site.Master $(document).ready code block.
Nice question.
You need to probably work with partial view here. I mean if your request is an ajax request, append the TempData again and the TempData will be outputted inside the partial view.
How will you send that partial view output as chunk of html?
I have a blog post about how you can send the partial view as string. The topic is different but you will get the idea:
http://www.tugberkugurlu.com/archive/working-with-jquery-ajax-api-on-asp-net-mvc-3-0-power-of-json-jquery-and-asp-net-mvc-partial-views
Here is an example:
[HttpPost]
public ActionResult toogleIsDone(int itemId) {
//Getting the item according to itemId param
var model = _entities.ToDoTBs.FirstOrDefault(x => x.ToDoItemID == itemId);
//toggling the IsDone property
model.IsDone = !model.IsDone;
//Making the change on the db and saving
ObjectStateEntry osmEntry = _entities.ObjectStateManager.GetObjectStateEntry(model);
osmEntry.ChangeState(EntityState.Modified);
_entities.SaveChanges();
var updatedModel = _entities.ToDoTBs;
//returning the new template as json result
return Json(new { data = this.RenderPartialViewToString("_ToDoDBListPartial", updatedModel) });
}
RenderPartialViewToString is a controller extension. you can find the the complete code for that from below link:
https://bitbucket.org/tugberk/tugberkug.mvc/src/6cc3d3d64721/TugberkUg.MVC/Helpers/ControllerExtensions.cs
After you have your html back on the client side code, append it you DOM and work on it. Animate it, show/hide it, do whatever you need with it

Categories