Unmapping view model (ko.mapping.toJSON), the first item exists only - knockout-mapping-plugin

I'm passing the following C# AjaxViewModel model:
namespace Db.ViewModels
{
public class DbAjaxViewModel
{
public DbAjaxViewModel() {
Products = new List<DbProductViewModel>();
}
public List<DbProductViewModel> Products { get; set; }
}
public class DbProductViewModel
{
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Price { get; set; }
public string CategoryId { get; set; }
}
}
..with the following code:
[HttpGet]
public ActionResult GetProductsAjax() {
var viewModel = _service.GetAllProductsAjaxViewModel();
return new JsonResult { Data = viewModel, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
Then I do the ko mapping:
function callBack(result) {
sprAdmin.product.viewModel = ko.mapping.fromJS(result);
ko.applyBindings(sprAdmin.product.viewModel, $("adminProductWrap")[0]);
}
$.ajax({
type: "GET",
url: url,
success: callBack
});
and it works great. I have this function to add an empty item to my viewModel:
addProduct: function () {
function product() {
this.Id = ko.observable("-1");
this.CategoryId = ko.observable("0");
this.Name = ko.observable("");
this.Description = ko.observable("");
this.Price = ko.observable("0");
}
debug.debug("adding new product");
sprAdmin.product.viewModel.Products.push(new product());
var debugArray = sprAdmin.product.viewModel.Products(),
debugData = debugArray[debugArray.length - 1];
debug.debug("id: " + debugData.Id() + ", name: " + debugData.Name() + ", description: " + debugData.Description() + ", price: " + debugData.Price() + ", categoryId: " + debugData.CategoryId());
}
as you can see, debug.debug retrieves the last item of Products() array and shows its contents, and this also works great.
But.
When I add more than one item to an empty array and do
var data = ko.mapping.toJSON(viewModel);
debug.debug("ajax submit data: " + data);
it shows the contents of unmapped viewModel converted to JSON like this:
{"Products":[{"Id":"1","CategoryId":"0","Name":"name","Description":"desc","Price":"0"},{}]}
The second (and further if exist) item of Products array is absolutely empty. It works always for the first item only.
Please help.
===
Solution:
First of all it's necessary to declare an observableArray:
viewModel: {
Products: ko.observableArray([])
}
and then to map like this:
sprAdmin.product.viewModel.Products(ko.mapping.fromJS(result.Products)());

Related

How can i execute filter from our JSON filter JSON?

I have a vue3 datagrid and I want to fill the data in this grid with filter by API. At the same time, I want to send the filter fields in the grid to the API as JSON and execute them according to this filter on the API side. How can I do this with AutoQuery?
[Route("/GetConnectors", "POST")]
public class GetConnectors : QueryDb<Connector>
{
public string Id { get; set; }
public string PageParameterJson { get; set; }
}
public class Connector
{
[PrimaryKey]
[AutoIncrement]
public long PKey { get; set; }
public string Id { get; set; }
public string Name { get; set; }
}
public class PageParameters
{
public string Field { get; set; }
public string Operand { get; set; }
public string Value { get; set; }
public string Type { get; set; }
}
It's an example PageParameter JSON;
[
{
"Field":"Name",
"Operand":"cn"//Contains
"Value":"test",
"Type":"string"
},
{
"Field":"Id",
"Operand":"eq"//Equal
"Value":"2",
"Type":"string"
}
]
public async Task<object> Any(GetConnectors query)
{
using var db = AutoQuery.GetDb(query, base.Request);
var filters = query.PageParameters.FromJson<List<PageParameter>>();
//How can I execute query with for CreateQuery?
var q = AutoQuery.CreateQuery(query, Request, db);
var sql = q.PointToSqlString();
return await AutoQuery.ExecuteAsync(query, q, base.Request, dbConnection);
}
Best Regards
i can't execute dynamic filters from server-side datagrid
The AutoQuery.CreateQuery returns OrmLite's Typed SqlExpression which has a number of filtering options inc .Where(), .And(), .Or(), etc.
So you should be able to populate it with something like:
foreach (var filter in filters)
{
var type = filter.Type switch
{
"string" => typeof(string),
_ => throw new NotSupportedException($"Type {filterType}")
};
var value = filter.Value.ConvertTo(type);
if (filter.Operand == "eq")
{
q.And(filter.Field + " = {0}", value)
}
else if (filter.Operand == "cn")
{
q.And(filter.Field + " LIKE {0}", $"%{value}%")
}
else throw new NotSupportedException(filter.Operand);
}
Note: I've rewritten API to be async as you should never block on async methods.

The challenge of uploading image. Other information are submitting to the database but the image is not uploading

This is the class of the customer
namespace test2.Models
{
public class Customer
{
public int Id { get; set; }
public string Full_Name { get; set; }
public Driver Driver { get; set; }
[Required]
[Display(Name = "Route")]
public int DriverId { get; set; }
[DataType(DataType.ImageUrl)]
[DisplayName("Driver's License ")]
public string ImageUrl { get; set; }
}
}
Controller
[HttpPost]
public ActionResult Save(Customer customer, HttpPostedFileBase file)
{
if (!ModelState.IsValid)
{
var viewModel = new CustomerFormViewModel
{
Customer = customer,
Drivers = _context.Drivers.ToList()
};
string imageLocation = "";
if ((file == null || file.ContentLength < 1))
{
ViewBag.Msg = "Please select an image";
return View();
}
if (!SaveImg(file, out imageLocation))
{
ViewBag.Msg = "An error occured while saving the image";
}
customer.ImageUrl = imageLocation;
return View("CustomerForm", viewModel);
}
//customer.ImageUrl = imageLocation;
if (customer.Id == 0)
_context.Customers.Add(customer);
else
{
var customerInDb = _context.Customers.Single(d => d.Id == customer.Id);
customerInDb.Full_Name = customer.Full_Name;
customerInDb.DriverId = customer.DriverId;
customerInDb.ImageUrl = customer.ImageUrl;
}
_context.SaveChanges();
return RedirectToAction("Index", "Customers");
}
public bool SaveImg(HttpPostedFileBase file, out string imageLocation)
{
imageLocation = "";
string serverPath = Server.MapPath("~/Images");
if ((file == null || file.ContentLength < 1))
{
//throw an exception showing that no file is present
}
var imageString = file.ToString();
var allowedExtensions = new[]
{
".jpg", ".png", ".jpg", ".jpeg"
};
var fileName = Path.GetFileName(file.FileName); //eg myImage.jpg
var extension = Path.GetExtension(file.FileName); //eg .jpg
if (allowedExtensions.Contains(extension.ToLower()))
{
string ordinaryFileName = Path.GetFileNameWithoutExtension(file.FileName);
string myFile = ordinaryFileName + "_" + Guid.NewGuid() + extension;
var path = Path.Combine(serverPath, myFile);
file.SaveAs(path);
string relativePath = "~/Images/" + myFile;
imageLocation = relativePath;
return true;
//return a success message here
}
else
{
//file save error
return false;
}
}
Include the file as part of the model:
public class Customer
{
public int Id { get; set; }
public string Full_Name { get; set; }
public Driver Driver { get; set; }
[Required]
[Display(Name = "Route")]
public int DriverId { get; set; }
[DataType(DataType.ImageUrl)]
[DisplayName("Driver's License ")]
public string ImageUrl { get; set; }
[NotMapped]
public HttpPostedFileBase ImageFile { get; set; }
}
Reference in the view like so:
#using (Html.BeginForm("Save", "Image", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="form-group">
#Html.TextBoxFor(model => model.ImageFile, new { htmlAttributes = new { #class = "form-control" }, type = "file" })
</div>
The not mapped property will ensure it is ignored in the db context. It can then be accessed using:
[HttpPost]
public bool Save(Customer customer)
{
if (customer.ImageFile != null)
{
// do something
}
}
It wouldn't be good practise to save the file to the database. Instead, store it in the project directory and either store the name or the image of the path to the image in the database.

How to search List of name which are present in cosmos documents

I have a list of name. I need to find which name is present in FirstName or LastName Property of Document in Collection.
I had tried the Linq query to archive this but it through error ("Object reference not set to an instance of an object.").
public class UserDoc
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string DocumentType { get { return "userdoc"; } private set { } }
}
List<string> Names = new List<string>() { "satya", "singh" };
IEnumerable<UserDoc> Users = await _dBRepository.GetItemsAsync<UserDoc>
(x => (Names.Contains(x.FirstName + " " + x.LastName))&& x.DocumentType == "userdoc");
public async Task<IEnumerable<T>> GetItemsAsync<T>(Expression<Func<T, bool>> predicate) where T : class
{
IDocumentQuery<T> query = _client.CreateDocumentQuery<T>(documentCollectionUri:
UriFactory.CreateDocumentCollectionUri(databaseId: _databaseId, collectionId: _collectionId),
feedOptions: new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = true })
.Where(predicate)
.AsDocumentQuery();
List<T> results = new List<T>();
while (query.HasMoreResults)
{
results.AddRange(await query.ExecuteNextAsync<T>());
}
return results;
}
According to your description. You code should be modified as below:
IEnumerable<UserDoc> Users = await _dBRepository.GetItemsAsync<UserDoc>
(x => (Names.Contains(x.FirstName)|| Names.Contains(x.LastName))&& x.DocumentType == "userdoc");
I have tested the code and it worked.
According to your error message, i think the the most likely reason is that the object _client point to Null, please check it and try again.

asp.net core delete everything with certain number

I want to delete all vragen(questions in english) with the classID for example number 5. It is possible to give a vraagID and a classID and the server deletes the question if it matches. But I want to delete all matching questions with only one request. Is this possible?
namespace AspIdentityServer.data
{
public class Vraag :Conversatie
{
public int VraagID { get; set; }
public int classID { get; set; }
public string Titel { get; set; }
public ICollection<Antwoord> Antwoord { get; set; }
public Vak Vak { get; set; }
}
}
--
// DELETE: api/Vraags/1/alles/5
[AllowAnonymous]
[HttpDelete("{id}/alles/{vakID}")]
public async Task<IActionResult> DeleteAlleVragen([FromRoute] int id, int vakID) {
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var vraag = await _context.Vraag.SingleOrDefaultAsync(m => m.VraagID == id);
if (vraag.classID == vakID)
{
_context.Vraag.Remove(vraag);
await _context.SaveChangesAsync();
}
return Ok(vraag);
}
You can always use the ExecuteSqlCommandAsync to execute your custom SQL queries. So write a single delete statements with appropriate where clause which will handle many rows as needed.
Here is a quick example
object[] paramsArray =
{
new SqlParameter
{
ParameterName = "#vraagId",
SqlDbType = SqlDbType.Int,
Value = id
},
new SqlParameter
{
ParameterName = "#classId",
SqlDbType = SqlDbType.Int,
Value = vakID
}
};
const string q = "DELETE FROM VraagWHERE VraagID=#vraagId and ClassId=#classId";
await _context.Database.ExecuteSqlCommandAsync(q, paramsArray);
Update the SQL statemenets and parameters as needed.

Navigation property is null

Album navigation property is null in SellingRequest when I try to load it by include() while it seems every thing is OK!
These are the codes:
public class Album
{
public int Id { get; set; }
public string Note { get; set; }
public virtual SellingRequest SellingRequest { get; set; }
public int? SellingRequestId { get; set; }
public List<Photo> Photos { get; set; }
public virtual MortgageAndRent MortgageAndRent { get; set; }
public int? MortgageAndRentId { get; set; }
}
public class SellingRequest
{
#region Properies
public int Id { get; set; }
public virtual Album Album { get; set; }
public int AlbumId { get; set; }
#endregion Properies
}
Here is where I create album for SellingRequest.
public ActionResult DoUpload(HttpPostedFileBase file, UploadPopupViewModel uploadPopupViewModel)
{
if (file != null && file.ContentLength > 0)
{
string path = Path.Combine(Server.MapPath("~/Contents/Images"), Path.GetFileName(file.FileName));
file.SaveAs(path);
Photo photo = new Photo() { Path = path };
ResponseMessage<Album> album = new ResponseMessage<Album>();
if(uploadPopupViewModel.SellingRequestId!=0)
album = _albumService.GetAlbumBySellingRequestId(uploadPopupViewModel.SellingRequestId);
if (uploadPopupViewModel.MortgageAndRentId != 0)
album = _albumService.GetAlbumByMortgageAndRentId(uploadPopupViewModel.SellingRequestId);
if (album.IsSuccess)
{
photo.AlbumId = album.Result.Id;
}
else
{
Album newAlbum = new Album();
if (uploadPopupViewModel.SellingRequestId != 0)
newAlbum.SellingRequestId = uploadPopupViewModel.SellingRequestId;
if (uploadPopupViewModel.MortgageAndRentId != 0)
newAlbum.MortgageAndRentId = uploadPopupViewModel.MortgageAndRentId;
ResponseMessage<Album> beingSavedAlbum = _albumService.Insert(newAlbum);
ResponseMessage<SellingRequest> sellingRequest = _sellingRequestService.GetById(uploadPopupViewModel.SellingRequestId);
if(sellingRequest.IsSuccess)
{
sellingRequest.Result.AlbumId = newAlbum.Id;
_sellingRequestService.Update(sellingRequest.Result);
}
if(beingSavedAlbum.IsSuccess)
photo.AlbumId = beingSavedAlbum.Result.Id;
}
ResponseMessage<Photo> beingSavedPhoto = _photoService.Insert(photo);
if (beingSavedPhoto.IsSuccess)
{
return RedirectToAction("UploadPopup", "Photo", uploadPopupViewModel);
}
else
{
ModelState.AddModelError("ImageError", beingSavedPhoto.ErrorMessages[0]);
return View("AddPhoto");
}
}
else
{
ModelState.AddModelError("ImageError", "Please choose a photo.");
return View("AddPhoto");
}
}
}
And Here is where I Try to query:
public IEnumerable<TEntity> GET(Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
IQueryable<TEntity> query = _context.Set<TEntity>();
if (filter != null)
query = query.Where(filter);
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
query = query.Include(includeProperty);
if (orderBy != null)
return orderBy(query).ToList();
else
return query.ToList();
}
And consequently, Here is where I try to load Album by include.
public List<SellingRequest> GetAllSellingRequests()
{
List<SellingRequest> sellingRequests = _sellingRepository.GET(null, includeProperties: "Address,Album.Photos", orderBy: sR => sR.OrderBy(s => s.RegisteredDate).OrderByDescending(s => s.RegisteredDate)).ToList();
return sellingRequests;
}
With this function I have the Address property but Album is null! It also happens vise versa. I mean when I include the sellingRequest from album, it returns me null, as well! This is while I can include all other entities with no problem!
Edit
This is the schema of my table in database:
SellingRequest Table
And this is the picture of Get.
Any suggestion would be appreciated in advance.
Regards

Resources