I have a problem when upload a file via Ajax , after de call is completed the page reloads , here is the code
function Save() {
var files1 = $("#file1").get(0).files;
var data = new FormData();
data.append("Data", JSON.stringify(GetData()));
for (i = 0; i < files1.length; i++) {
data.append("file" + i, files1[i]);
}
var resp =
{
service: "File/SaveFile",
sender: data,
progress: null,
funct: null,
antes: null,
despues: null
};
var response = CallServiceUpload(resp);
response.done(function (responseData, textStatus) {
var controlInput = $("#file1");
controlInput.replaceWith(controlInput = controlInput.val('').clone(true));
});
return response;
}
function GetData() {
x =
{
ID: 1
}
return x;
}
this.CallServiceUpload = function (obj) {
return $.ajax({
type: "POST",
url: "api/" + obj.service,
data: obj.sender,
contentType: false,
processData: false,
error: function (message) {
alert(message.responseText);
}
});
}
and here is the server code using ASP.NET Web Api
using DataManager.Estruct.DTO;
using DataManager.Logic;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
namespace WebApp.Controllers
{
public class FileController : ApiController
{
#region
[HttpPost]
[ActionName("SaveFile")]
public async Task<JObject> SaveFile()
{
// Check if the request contains multipart/form-data.
var httpContent = Request.Content;
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/App_Data");
try
{
StringBuilder sb = new StringBuilder(); // Holds the response body
var provider = new CustomMultipartFormDataStreamProvider(root);
// Read the form data and return an async task.
await Request.Content.ReadAsMultipartAsync(provider);
string jsonData = provider.FormData.GetValues("Data")[0];
List<string> deletefiles = new List<string>();
foreach (var file in provider.FileData)
{
FileInfo fileInfo = new FileInfo(file.LocalFileName);
//Process File
}
provider.FileData.Clear();
foreach (string deletefile in deletefiles)
{
try
{
File.Delete(deletefile);
}
catch (Exception ex)
{
string error = ex.InnerException.Message;
}
}
object x = new { data = "ok"};
return JObject.FromObject(x);
}
catch (Exception ex)
{
// string Mensaje = LCuenta.LogError(null, ex, System.Reflection.MethodBase.GetCurrentMethod().Name);
var error = new { error = ex.Message };
return JObject.FromObject(error);
}
}
#endregion
}
public class CustomMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
{
public CustomMultipartFormDataStreamProvider(string path) : base(path) { }
public override string GetLocalFileName(HttpContentHeaders headers)
{
return headers.ContentDisposition.FileName.Replace("\"", string.Empty);
}
}
}
I Alredy use this code for another app , but in this case after the executing the javascript method Save , the complete page reloads , if the file is small o the call has no files only data y does not reload , the page html is on asp web view using mvc , but is only a container all the code is on javascript.
thanks!;
On button click use preventDefault
Ex
$("#buttonID").click(function(event){
event.preventDefault();
});
Related
I´ve downloaded the Forge Design Automation sample from the following link:
https://learnforge.autodesk.io/#/tutorials/modifymodels
But the downloable code example is not working fine. When any async method who involves the DesignAutomation API is called I get -> Value cannot be null. (Parameter 'ForgeConfiguration.ClientId'). So, I would like to know how it works and how I can set the ClientId in the ForgeConfiguration class or else if I making something else wrong. I attach a fragment of code where I get the error.
[HttpGet]
[Route("api/forge/designautomation/engines")]
public async Task<List<string>> GetAvailableEngines()
{
List<string> allEngines = new List<string>();
try
{
dynamic oauth = await OAuthController.GetInternalAsync();
// define Engines API
string paginationToken = null;
while (true)
{
Page<string> engines = await _designAutomation.GetEnginesAsync(paginationToken);
allEngines.AddRange(engines.Data);
if (engines.PaginationToken == null)
break;
paginationToken = engines.PaginationToken;
}
allEngines.Sort();
}
catch (Exception error) {
throw error;
}
return allEngines; // return list of engines
}
And the call of the method:
function prepareLists() {
list('engines', 'api/forge/designautomation/engines');
}
function list(control, endpoint) {
$('#' + control).find('option').remove().end();
jQuery.ajax({
url: endpoint,
success: function (list) {
if (list.length === 0)
$('#' + control).append($('<option>', { disabled: true, text: 'Nothing found' }));
else
list.forEach(function (item) { $('#' + control).append($('<option>', { value: item, text: item })); })
}
});
}
Did you forget to set the Forge App Keys in the Environment Variables of your project, check the page at https://learnforge.autodesk.io/#/environment/setup/netcore_da
I am currently using jsTree v3.3.10 and attempting to load the structure via a Web API call.
JavaScript:
$('#ksbBrowser').jstree({
core: {
data: {
type: 'GET',
dataType: 'json',
contextType: 'application/json',
url: function (node) {
if (node.id == "#") {
return '/api/search/talent/ksbtree/root';
}
else {
return '';
}
},
data: function (node) {
return { id: node.id };
}
}
}
});
C# WebAPI EndPoint Code:
[HttpGet, Route("api/search/talent/ksbtree/{Type}")]
public String GetKSBTree(String Type)
{
List<DataModels.JSTreeNode> lNodes = new List<JSTreeNode>();
String sJSON = "";
switch (Type)
{
case "root":
var first = new[] {
new {
id = "root-id",
text = "KSBs",
state = new { opened = true },
children = true
}
};
sJSON = JSONHelper.Serialize(first);
break;
default:
break;
}
return sJSON;
}
I am getting json returned via the call and the appropriate contentType headers are there, but jsTree is not loading the tree correctly. This is the sample return of the JSON via postman:
"[{\"id\":\"root-id\",\"text\":\"KSBs\",\"state\":{\"opened\":true},\"children\":true}]"
But as you can see here, jsTree is not processing the JSON correctly.
Does anyone have any idea at all what I am doing wrong.
I figured this out. The WebAPI was returning type of string and jsTree does not do it's own parseJSON internally. To fix this I changed the return type of my end point to be an HTTPResponseMessage.
public HttpResponseMessage GetKSBTree(String Type)
Then I format the response message and return it:
HttpResponseMessage rmMessage = new HttpResponseMessage() { Content = new StringContent(sJSON) };
rmMessage.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
return rmMessage;
I would upload the file in Angular using upload component
Here's my HTML:
<p-fileUpload mode="basic" name="demo[]" customUpload="true" accept="image/*" maxFileSize="1000000" (uploadHandler)="upload($event)"></p-fileUpload>
in my ts I print param value
upload(event) {
console.log(event)
}
I get only metadata and not blob content
{"files":[{"objectURL":{"changingThisBreaksApplicationSecurity":"blob:https://prime-ng-file-uploading.stackblitz.io/d429e761-c391-45fa-8628-39b603e25225"}}]}
I would also get file content to send via API to the server
Here's a stackblitz demo
In the official documentation you have an example:
export class FileUploadDemo {
uploadedFiles: any[] = [];
constructor(private messageService: MessageService) {}
onUpload(event) {
for (let file of event.files) {
this.uploadedFiles.push(file);
}
this.messageService.add({
severity: 'info',
summary: 'File Uploaded',
detail: ''
});
}
}
When I used primeNG, I did it like this (for uploading only 1 file) :
HTML
<p-fileUpload name="myfile[]" customUpload="true" multiple="multiple" (uploadHandler)="onUpload($event)" accept="application/pdf"></p-fileUpload>
component.ts
export class AlteracionFormComponent {
uplo: File;
constructor(private fileService: FileUploadClientService) {}
onUpload(event) {
for (let file of event.files) {
this.uplo = file;
}
this.uploadFileToActivity();
}
uploadFileToActivity() {
this.fileService.postFile(this.uplo).subscribe(data => {
alert('Success');
}, error => {
console.log(error);
});
}
}
And my service (in Angular)
service.ts
postFile(id_alteracion: string, filesToUpload: FileUploadModel[], catalogacion: any): Observable<any> {
let url = urlAPIAlteraciones + '/';
url += id_alteracion + '/documentos';
const formData: FormData = new FormData();
formData.append('json', JSON.stringify(catalogacion));
for (let file of filesToUpload) {
formData.append('documento', file.data, file.data.name);
}
console.log(formData);
let headers = new HttpHeaders();
return this._http.post(url, formData, { headers: headers });
}
Hope that helps
I'm trying to use the standard PrimeNG approach for uploading multiple files at once.
<p-fileUpload name="myfile[]" [url]="MyApiUrl" multiple="multiple"></p-fileUpload>
In my ApiController, I get the following:
public List<FileModel> Post()
{
var files = HttpContext.Current.Request.Files;
var result = new List<FileModel>();
if (files.Count > 0)
{
Guid guid = Guid.NewGuid();
var path = System.IO.Path.Combine(System.Web.Configuration.WebConfigurationManager.AppSettings["UploadFileLocation"], guid.ToString() + "/");
System.Web.HttpContext.Current.Session["guid"] = guid;
if (!System.IO.Directory.Exists(path)) { System.IO.Directory.CreateDirectory(path); }
foreach (string fileName in files.AllKeys)
{
var file = files[fileName];
var filePath = path + file.FileName;
file.SaveAs(filePath);
result.Add(_data.InsertFile(FileModel.Create(path, file.FileName)));
}
}
return result;
}
The problem I'm having is that "fileName" in var file = files[fileName] always equals the first file in the group of files uploaded. I don't know if this is an issue with HttpContext.Current.Request.Files or a PrimeNG bug. Has anyone ran into this type of problem?
Doing it this way because I want to store the guid in my session and grab it later on when the form is submitted...
Ok, this might be simple, I'm having a simple $.post call to server sending string array as parameters..
$.get('/home/ReadCalPacTagValue', data, function (data) {
data = $.parseJSON(data);
if (data.length != 0) {
var ReadFromDb = data[0]["PushToDb"].replace('PushToDb','ReadFromDb');
var DBAckno = ReadFromDb.replace('ReadFromDb', 'DataAck');
var FIdTag = ReadFromDb.replace('ReadFromDb', 'FluidTypeId');
var UserIdTag = ReadFromDb.replace('ReadFromDb', 'UserId');
var UniqueIdTag = ReadFromDb.replace('ReadFromDb', 'UniqueRecordId');
var dbconnTag = ReadFromDb.replace('ReadFromDb', 'DatabaseConnectionString');
updateTags = [dbconnTag,FIdTag,ReadFromDb, UserIdTag,UniqueIdTag];
actionvalue = ["", fluidtypeid, '1', userid, uniqueID];
var data_Tags = { updateTags: updateTags, actionvalue: actionvalue }
$.post('/home/WriteCalPacTagValue', data_Tags, function (response) {
//var Path = "Config/16_CalPac/" + FluidType + "/" + metername + "/" + FileName
//$.cookie('FileName', FileName, { expires: 7, path: '/' });
//$.cookie('FilePath', Path, { expires: 7, path: '/' });
//$.cookie('ModuleName', "CalPac", { expires: 7, path: '/' });
//window.open('../home/CalPac', '_blank');
});
} else {
swal("Error !", "Data operation tag not binded for this product", "warning");
}
})
my problem is, every time it makes $.post call, server is getting null values int prarameters..
public void WriteCalPacTagValue(string[] updateTags, string[] actionValue)
{
string[] writetags = { };
DanpacUIRepository objNewTag = new DanpacUIRepository();
if (updateTags.Count() > 0)
{
actionValue[0] = ConfigurationManager.AppSettings["DBString"].ToString();
for (int i = 0; i < updateTags.Count(); i++)
{
writetags = updateTags[i].Replace("<", "").Replace(">", ">").Split('>');
objNewTag.WriteTag(writetags, actionValue[i]);
}
}
}
I'm not getting what I've done wrong here.. whereas same function is working from another JS file with some difference string into array updateTags.
any help?
Having
public class DataTags
{
public string[] UpdateTags { get; set; }
public string[] ActionValue { get; set; }
}
At the server: Change the method to this
[HttpPost()]
public void WriteCalPacTagValue([FromBody]DataTags data_Tags)
{
}
At the client: call it
$.ajax({
type: 'POST',
url: '/home/WriteCalPacTagValue',
data: data_Tags,
success: function (response) {
//your code
}
});
Also you can send the whole data as json string using data: JSON.stringify(data_Tags), in javascript code the change the WriteCalPacTagValue to accept a single string at the parameter and deserialize it in C# code at the server side.
EDIT if you cannot change the server side code, you may follow this as stated in the comments.
I am using a jQuery plugin, jTable. The plugin has the following function to load the table:
$('#PersonTable').jtable('load', { CityId: 2, Name: 'Halil' });
The values in the load function is send as POST data. The plugin also sends two query string parameters (jtStartIndex, jtPageSize) through the URL for paging the table.
An example in the documentation shows a function on how to handle this in ASP.NET MVC but not in Web API Example :
[HttpPost]
public JsonResult StudentListByFiter(string name = "", int cityId = 0, int jtStartIndex = 0, int jtPageSize = 0, string jtSorting = null)
{
try
{
//Get data from database
var studentCount = _repository.StudentRepository.GetStudentCountByFilter(name, cityId);
var students = _repository.StudentRepository.GetStudentsByFilter(name, cityId, jtStartIndex, jtPageSize, jtSorting);
//Return result to jTable
return Json(new { Result = "OK", Records = students, TotalRecordCount = studentCount });
}
catch (Exception ex)
{
return Json(new { Result = "ERROR", Message = ex.Message });
}
}
How my function currently looks: It works fine except that I can't manage to read the POST data (name param):
public dynamic ProductsList(string name = "", int jtStartIndex = 0, int jtPageSize = 0 )
{
try
{
int count = db.Products.Count();
var products = from a in db.Products where a.ProductName.Contains(name) select a;
List<Product> prods = products.OrderBy(x => x.ProductID).ToList();
return (new { Result = "OK", Records = prods, TotalRecordCount = count });
}
catch (Exception ex)
{
return (new { Result = "ERROR", Message = ex.Message });
}
}
My jTable load: (This get called when the user enters text in a input)
$('#ProductTable').jtable('load', {
name: $('#prodFilter').val()
});
I would appreciate any help with how to read both the string parameters in the URL and the POST data in a Web API function.
EDIT:
I used an alternative way to send the data to the API. Instead of sending it in the load function formatted as JSON I used a function for the listAction and sent the data through the URL (See jTable API reference for details):
listAction: function (postData, jtParams) {
return $.Deferred(function ($dfd) {
$.ajax({
url: 'http://localhost:53756/api/Product/ProductsList?jtStartIndex=' + jtParams.jtStartIndex + '&jtPageSize=' + jtParams.jtPageSize + '&name=' + $('#prodFilter').val(),
type: 'POST',
dataType: 'json',
data: postData,
success: function (data) {
$dfd.resolve(data);
},
error: function () {
$dfd.reject();
}
});
});
}
To reload the table based on your filtered results:
$('#ProductTable').jtable('load');
Instead of this:
$('#ProductTable').jtable('load', {
name: $('#prodFilter').val()
});
Try applying the [FromBody] attribute to the name parameter
public dynamic GetProductList([FromBody]string name = "", int jtStartIndex = 0, jtPageSize = 0)
{
...
}
The default binder in Web API will look in the URI for simple types like string, specifying the FromBody attribute will force it to look in the body.