How to update MVC model clientside with Javascript? - javascript

In a ASP.NET MVC project I'm uploading image files to web server using FineUploader jQuery plugin. File uploading part works fine, but now I need to save the uploaded image names to database with the corresponding model details (Product Details with Product Image names).
Models :
public class Product
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
...
public virtual IEnumerable<ProductImage> Images { get; set; }
}
public class ProductImage
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string FileName { get; set; }
}
This is my HTML & JavaScript code to upload the file & display uploaded file in the page when the upload is completed
...
<div id="fine-uploader"></div>
<div id="divImgs">
<ul>
</ul>
</div>
....
<script>
function createUploader() {
var uploader = new qq.FineUploader({
element: document.getElementById('fine-uploader'),
debug: true,
request: {
endpoint: '#Url.Action("UploadFile", "Upload")'
},
validation: {
allowedExtensions: ['jpeg', 'jpg', 'gif', 'png']
},
deleteFile: {
enabled: true,
forceConfirm: true,
endpoint: '#Url.Action("DeleteFile", "Upload")'
},
callbacks: {
onComplete: function (id, fileName, responseJSON) {
if (responseJSON.success) {
$('#divImgs ul').append(
$('<li>').append(
$('<img>').click(
function DeleteFileCall() {
$.ajax({
type: "POST",
url: '#Url.Action("DeleteFile", "Upload")' + '/' + fileName,
contentType: "application/json; charset=utf-8",
dataType: "html"
});
$(this).parent().remove();
}).attr('src', responseJSON.uploadedFilePath))
);
}
}
}
});
}
window.onload = createUploader;
</script>
How can I add the uploaded file names to Model with javascript & update the database only when user saves model data.

if you're uploading a Stream body in your controller, you can pass the filename as a query string parameter and map that to a function parameter for saving later.
example from another project
[WebInvoke(UriTemplate = "/AddImage/{filename}", Method="POST")]
public PrimitiveResponse AddImage(string filename, Stream imageData)
{
//magic happens here
}

Related

How to upload files with additional file data in asp.net core

I am trying to upload multiple files (documents) with additional data per file.
Ie. I would like to upload multiple documents like this:
[{
documentFile: file
documentVersion: 2,
documentOperation: "createNew"
...
},
{
documentFile: file2.doc
documentVersion: 1,
documentOperation: "createNew"
...
}]
And ideally would like that information to be populated in the model but this is not a requirement.
I am using Aurelia Fetch client to send data using FormData.
Is this possible?
If your model is like:
public class Documents
{
public IFormFile documentFile { get; set; }
public string documentVersion { get; set; }
public string documentOperation { get; set; }
}
You can see my test.
Action:
[HttpPost]
public IActionResult Demo(List<Documents> documents)
{
//...
}
Send data by postman:
Result:

How do I access data returned from a controller invoked by an ajax call in an MVC View

I have an MVC 5 view with the following JavaScript which is getting an error after invoking an action method on a controller:
<script type="text/javascript">
$('#ddlvendors').change(function () {
var descHtml = "";
var vendorId = $(this).val();
$.ajax(
{
type: "POST",
data: { vendorId: vendorId },
url: '#Url.Action("PurchaseOrderVendor")',
datatype: "json",
success: function (aVendorObject) {
alert(aVendorObject.Name);
},
error: function (req, status, error) {
alert(error);
}
});
});
</script>
The controller action method is as follows:
[HttpPost]
public ActionResult PurchaseOrderVendor( int vendorId)
{
Vendor aVendor=VendorServices.GetVendor(vendorId);
return Json(aVendor);
}
The vendor object being returned is as follows:
public class VendorViewModel
{
public int VendorId { get; set; }
public string Name { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public string Description { get; set; }
public string ContactName { get; set; }
public string Phone { get; set; }
}
Using the Visual Studio 2017 debugger I can see the vendor data is correctly getting filled on the controller side. If I don't try to access any member data the ajax call completes without an error. However, when I try to access any part coming in as aVendorObject such as aVendorObject.Name I get a browser error saying "Internal Server Error". How can I fix my success handler in the ajax call so I can access members of the Vendor object being returned from the controller?
Thanks in advance.
The LazyLoading feature of EntityFramework 6 did not have the Vendor object available when it was needed. I added a line in the VendorServices class to turn off LazyLoading which fixed the problem. Below is the method where I turn off LazyLoading for this particular VendorService method:
static public Vendor GetVendor(int aVendorId)
{
Vendor vendor;
using (RgmSiteDAL RgmSiteDALCtx = new RgmSiteDAL())
{
//** Now setting LazyLoadingEnabled to false.
RgmSiteDALCtx.Configuration.LazyLoadingEnabled = false;
vendor = RgmSiteDALCtx.Vendor
.Where(v => v.VendorId == aVendorId)
.FirstOrDefault<Vendor>();
}
return vendor;
}
I found out that I can also fix the problem if I include any navigation properties defined with the Vendor entity as in the following:
vendor = RgmSiteDALCtx.Vendor
.Where(v => v.VendorId == aVendorId)
.Include(v => v.PurchaseOrder) //because is in Vendor navigation property
.FirstOrDefault<Vendor>();
For my situation I will stick with the first solution which sets LazyLoadingEnabled to false. This is because the option to generate my entities from my existing database setup my PurchaseOrder table as a navigation property for my Vendor which I believe is incorrect. My Vendor object does not need anything from my PurchaseOrder entity when I query for Vendor information. I will look into removing the PurchaseOrder navigation property from my Vendor entity because I believe it was incorrectly setup by the create entities from database tool in Visual Studio.

Upload multiple files each with additional information in spring

I'm new to spring boot and js and i'm trying to upload multiple files each having additionl information like description etc.
Objects :
public class BookDto {
private String title;
private String author;
private List<PageDto> pageDtoList;
// getters setters
}
public class PageDto {
private String description;
private MultipartFile file;
// getters setters
}
Controller :
public class UploadController{
#PostMapping("/upload")
public ResponseEntity createGenre(#RequestBody BookDto bookDto){
// do something with data
}
}
Html :
<form action="upload" method="post" enctype="multipart/form-data">
<input type="file" multiple onclick="postRequest(event)">
<input type="submit" value="Upload" name="submit">
</form>
JS :
function postRequest(event){
event.preventDefault();
var files = [].slice.call(event.target.files);
var pageList = [];
for (var i=0; i<files.length; i++) {
pageList.push(new Page( i + "some description",files[i]));
}
var newBook = new Book();
newbook.pageList = pageList;
book.author = "author1";
book.title = "title1";
$.ajax({
type: "POST",
data: // i don't really know what to put here,
url: "/upload",
success: function (response) {
// success
},
error: function (result) {
// error
}
});
}
function Book(title, author, chapter, pageList){
this.title = title;
this.author = author;
this.pageList = pageList;
}
function Page(description, file) {
this.description = description;
this.file = file;
}
I would like to know if it is possible to upload files as described by the objects or do i have to upload them seperately.
In order to create a book instance from a request, considering you have a route such as :
#PostMapping("/createBook")
public ResponseEntity createBook(#RequestBody BookDto bookDto){
// do something with data
}
you can from client proceed to following :
const book = {
author: "George Orwell",
title: "1984",
pageDtoList: []
};
$.ajax({
type: "POST",
data: book,
url: "/createBook",
success: function (response) {
// success
},
error: function (result) {
// error
}
});
You can then add pages with same logic, but with a file set to null temporary, and upload file after, given a page id.
#PostMapping("/addPageToBook")
public ResponseEntity addPage(#RequestParam("bookid") String bookId,
#RequestBody PageDto pageDto){
// add a page instance to your book
}
And after you can set page content :
#PostMapping("/setPageContent")
public ResponseEntity setPage(#RequestParam("bookid") String bookId,
#RequestParam("pageid") String pageId,
#RequestParam("file") MultipartFile content){
// set content to page, ensure book dto is updated with last page instance
}
You will need to use https://developer.mozilla.org/en-US/docs/Web/API/FormData for AJAX uploading, but maybe (depending on your use case) a simple file input button + submit can be enough.

String property not deserialized

I don't understand why only the string property Search.Value is not being deserialized in my ASP.NET MVC5 Controller. Please see this:
The Json-structure sent from the Client:
{
"draw":1,
// ...
"start":0,
"length":50,
"search":{
"value":"This is always null in my controller",
"regex":false
}
}
The model I have server-side:
public class AsyncDataTableRequest
{
public int Draw { get; set; }
public int Start { get; set; }
public int Length { get; set; }
public Search Search { get; set; }
public string Value { get; set; }
}
public class Search
{
public string Value { get; set; }
public bool Regex { get; set; }
}
The controller where I would like to do something with Search.Value:
public JToken AsyncLogFetching(AsyncDataTableRequest req)
{
// req.Search.Value is null here, all other properties seem correct
...
}
Thank you for any help!
Edit:
For a sample search with "NewYork", this the request from the tab "request header" in IE Developer tools:
GET /Log/AsyncLogFetching?draw=3&start=0&length=50&search%5Bvalue%5D=NewYork&search%5Bregex%5D=false&_=1438350434912 HTTP/1.1
The tab "request text" in IE Developer tools says "No data to display".
This is the snippet that does the GET-Request, it's copy & pasted from the jQuery DataTables Pipelining example:
settings.jqXHR = $.ajax({
"type": conf.method, // GET
"url": conf.url,
"data": request,
"dataType": "json",
"contentType": "application/json",
"cache": false,
"success": function (json) {
// ...
}
});
try to use JSON.stringify(yourObject) for send the data from client to controller
please take the reference of following
How to send nested json object to mvc controller using ajax

ASP MVC 5 Auto Complete not working

i am pretty new to ASP MVC 5 and after reading several tutorials I still cannot seem to implement a simple autocomplete feature. My issue is that the data that the View is receiving is [Object object] and I have no idea why. The number of fetched words is correct, the only problem is that it does not show "words" just [Object object].
So this is my model:
public class Vassal
{
public string Name { get; set; }
public string Type { get; set; }
public int ID { get; set; }
public class VassalDBContext : DbContext
{
public DbSet<Vassal> Vassals { get; set; }
}
}
This is my Controller (VassalControlller)
public JsonResult AutoComplete(string search)
{
var vassalNames = from m in db.Vassals
select m;
if (!String.IsNullOrEmpty(search))
{
vassalNames = vassalNames.Where(s => s.Type.Contains(search));
}
return Json(vassalNames, JsonRequestBehavior.AllowGet);
}
and this is my View
#model IEnumerable<webVassal.Models.Vassal>
#{
ViewBag.Title = "Search";
}
<div class="ui-widget">
<label for="tags">Tags: </label>
<input id="tags" />
</div>
<script type="text/javascript" >
$(function () {
$('#tags').autocomplete({
source: function (request, response) {
$.ajax({
url: '#Url.Action("AutoComplete")',
dataType: "json",
contentType: 'application/json, charset=utf-8',
data: {
search: $("#tags").val()
},
success: function (data) {
response($.map(data, function (item) {
return {
label: item
};
}));
},
error: function (xhr, status, error) {
alert(error);
}
});
},
minLength: 1
});
});
</script>
I am using Jquery 2.1.1, jquery-ui.min.js and jquery.ui.widget.js
Also if I were to adapt the code above to use the Twitter bootstrap typeahead plugin, what would I need to do? I tried following the instructions on this link http://deanhume.com/home/blogpost/twitter-bootstrap-typeahead-and-asp-net-mvc---key-value-pairs/88 and I was getting a hasOwnProperty error.
I apologize for any format issues i am kind of new on posting code issues.
Any help is very much appreciated.
Thank you for your time
try to replace
return {
label: item
};
with
return {
label: item.Name
};
you are returning an array of Objects not strings, so you will need to access the Name property on each in your success clause.
i think you should ask the bookstrap typeahead question separately.

Categories