How append whole object to formData - asp.net

I need to send image list and product data to ASP.net api via formData. I succesfully sended images but now i dont really know how to append whole object. I have seen some ways to do that in JS JSON.stringfy(object) or Object.keys(object).forEach(key => formData.append(key, object[key])); but it doesnt works for me.
angular http service
updateProduct(imageProductVM:ProductImageViewmodel): Observable<any> {
const formData = new FormData()
// imageProductVM.product ??
for (const photo of imageProductVM.files) {
console.log(photo)
formData.append('files', photo)
}
return this.http.post(this.apiURL + '/product/', formData, {headers:{"ContentType": "multipart/form-data"}})
}
asp.net api
[HttpPost]
public async Task<ActionResult> AddProduct([FromForm] ProductService ser)
{
return Ok();
}
public class ProductService
{
public Product? product { get; set; }
public List<IFormFile>? files { get; set; }
}

In fact, I forgot to say that my product object also has nested objects. Thanks W.S for sharing the info.
This answer helped me
to understand what an object should look like for ASP.net , Here's how it should look in my case:
product.id "*value*"
product.supplierId "*value*"
product.supplierName *value*
product.title "*value*"
product.description "*value*"
product.vendor "*value*"
product.vendorId "*value*"
product.documents[0].id *value*
product.documents[0].url
product.documents[0].keywords
product.attributes[0].attributeId *value*
product.attributes[0].attributeName *value*
product.attributes[0].type A
product.attributes[0].value 2
And then I used the following code to convert my object to a compatible view:
productEntriesIteration(object:object, j:number, nestedKey:string) {
Object.entries(object).forEach(([key, value], i)=> {
if (value) {
if (typeof value == "string") {
this.appendSingleField(key, nestedKey,j,value);
}
else if (typeof value == "number") {
if ( Number(value) === Number(value) && Number(value) !== (Number(value) | 0)) {
value = value.toString().replace(".", ',')
}
this.appendSingleField(key,nestedKey,j,value)
}
else if (typeof value.getMonth === 'function') {
this.appendSingleField(key, nestedKey, j, value.toISOString())
}
else if (Array.isArray(value)) {
for (let val in value) {
if (typeof value[val] == "object") {
this.productEntriesIteration(value[val], Number(val), key)
}
else if (typeof value[val] == "number"){
this.appendSingleField(key, nestedKey, j, value[val])
}
else {
this.appendSingleField(key, nestedKey, j, value[val])
}
}
} else if (typeof value == "object") {
this.productEntriesIteration(value, -1, key)
}
}
})
return this.formData
}
appendSingleField(key:string, nestedKey:string, i:number, value:any) {
if (i == null) {
this.formData.append('product.'+key+'',value)
} else if (i == -1) {
this.formData.append('product.'+nestedKey+'.'+key,value)
} else {
this.formData.append('product.'+nestedKey+'['+i+'].'+key,value)
}
}
I hope this helps someone

Related

Problem with adding new object to data base

Hi i have an error when i trying add object to database. Error message is:
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=472540 for information on understanding and handling optimistic concurrency exceptions.
My adding methods:
public void AddProduct(string category, FormCollection formCollection, HttpPostedFileBase image) //Dodaje nowy produkt do bazy.
{
var product = GetNewProduct(category);
var EfContext = GetEfContext(category);
foreach(var property in product.GetType().GetProperties())
{
if(property.Name != "ImageData" && property.Name != "ImageMimeType")
{
var NewValue = Convert.ChangeType(formCollection[property.Name], property.PropertyType);
property.SetValue(product, NewValue);
}
else
{
if (property.Name == "ImageData")
{
property.SetValue(product, new byte[image.ContentLength]);
}
if(property.Name == "ImageMimeType")
{
property.SetValue(product, image.ContentType);
}
if(product.GetType().GetProperty("ImageData").GetValue(product) != null && product.GetType().GetProperty("ImageMimeType").GetValue(product) != null)
{
image.InputStream.Read((byte[])product.GetType().GetProperty("ImageData").GetValue(product), 0, image.ContentLength);
}
}
}
EfContext.GetType().GetMethod("AddProduct").Invoke(EfContext, new object[] { product });
}
And
public void AddProduct(GPU product)
{
product.Product_ID = productContext.items.Count() != 0 ? productContext.items.OrderByDescending(x => x.ProductID).Select(x => x.ProductID).FirstOrDefault() + 1 : 1;
context.GPUs.Add(product);
context.SaveChanges();
}

ASP.NET MVC - Session Variables are null in Callback from server ActionResult method

I am implementing CoinPayments IPN in my application and I have trouble with passing data to the method that take their Callback. I have tried like everything I could find: TempData, SessionVariables, tried to implement it somewhere in forms and maybe Request it but that didn`t work for me. So I also tried to implement it with Global static variables. And it worked! But then came another issue: if more than one user were to buy something from website at the same time or even in between any callbacks their data will get mixed. So here I am, trying again to make Session Variables work and have no clue why they are not working as I used them before. Probably what I can think of is that because its a callback from CoinPayments and I handle something wrongly.
Here is the code I have right now: Tho I tried different variations like implementing Session in Get Payment method. Now I ended up with it and it still comes out as null in POST METHOD.
Class for handling Session Variables:
public static class MyGlobalVariables
{
public static int TokenChoice
{
get
{
if (System.Web.HttpContext.Current.Session["TokenChoice"] == null)
{
return -1;
}
else
{
return (int)System.Web.HttpContext.Current.Session["TokenChoice"];
}
}
set
{
System.Web.HttpContext.Current.Session["TokenChoice"] = value;
}
}
public static int PaymentChoice
{
get
{
if (System.Web.HttpContext.Current.Session["PaymentChoice"] == null)
{
return -1;
}
else
{
return (int)System.Web.HttpContext.Current.Session["PaymentChoice"];
}
}
set
{
System.Web.HttpContext.Current.Session["PaymentChoice"] = value;
}
}
public static string CurrentUser
{
get
{
System.Web.HttpContext.Current.Session["CurrentUser"] = System.Web.HttpContext.Current.User.Identity.Name;
return (string)System.Web.HttpContext.Current.Session["CurrentUser"];
}
}
}
Class that returns view where you click on CoinPayments button:
public ActionResult Payment(int tokenChoice, int paymentChoice)
{
ViewBag.Payment = paymentChoice;
MyGlobalVariables.PaymentChoice = paymentChoice;
MyGlobalVariables.TokenChoice = tokenChoice;
return View();
}
Callback class that handles Callback from CoinPayments:
[HttpPost]
public ActionResult Payment()
{
NameValueCollection nvc = Request.Form;
var merchant_id = id;
var ipn_secret = secret;
var order_total = MyGlobalVariables.PaymentChoice;
if (String.IsNullOrEmpty(nvc["ipn_mode"]) || nvc["ipn_mode"] != "hmac")
{
Trace.WriteLine("IPN Mode is not HMAC");
return View();
}
if (String.IsNullOrEmpty(HTTP_HMAC))
{
Trace.WriteLine("No HMAC signature sent");
return View();
}
if (String.IsNullOrEmpty(nvc["merchant"]) || nvc["merchant"] != merchant_id.Trim())
{
Trace.WriteLine("No or incorrect Merchant ID passed");
return View();
}
//var hmac = hash_hmac("sha512", request, ipn_secret.Trim());
var txn_id = nvc["txn_id"];
var item_name = nvc["item_name"];
var item_number = nvc["item_number"];
var amount1 = nvc["amount1"];
var amount2 = float.Parse(nvc["amount2"], CultureInfo.InvariantCulture.NumberFormat);
var currency1 = nvc["currency1"];
var currency2 = nvc["currency2"];
var status = Convert.ToInt32(nvc["status"]);
var status_text = nvc["status_text"];
Trace.WriteLine(status);
if (currency1 != "USD") {
Trace.WriteLine("Original currency mismatch!");
return View();
}
if (Convert.ToInt32(amount1) < Convert.ToInt32(order_total))
{
Trace.WriteLine("Amount is less than order total!");
return View();
}
if (status >= 100 || status == 2) {
using (MyDatabaseEntities1 dc = new MyDatabaseEntities1())
{
var account = dc.Users.Where(a => a.Username == MyGlobalVariables.CurrentUser).FirstOrDefault();
if (account != null && account.Paid == 0)
{
Trace.WriteLine("Payment Completed");
Trace.WriteLine("Tokens to add: " + MyGlobalVariables.TokenChoice);
account.Tokens += MyGlobalVariables.TokenChoice;
account.Paid = 1;
dc.Configuration.ValidateOnSaveEnabled = false;
dc.SaveChanges();
}
}
} else if (status < 0)
{
Trace.WriteLine(
"payment error, this is usually final but payments will sometimes be reopened if there was no exchange rate conversion or with seller consent");
} else {
using (MyDatabaseEntities1 dc = new MyDatabaseEntities1())
{
var account = dc.Users.Where(a => a.Username == MyGlobalVariables.CurrentUser).FirstOrDefault();
if (account != null)
{
account.Paid = 0;
dc.Configuration.ValidateOnSaveEnabled = false;
dc.SaveChanges();
}
}
Trace.WriteLine("Payment is pending");
}
return View();
}
As you can see there are only 3 variables I need to handle.
Also someone might ask why I use Session Variable for Current.User?
Well for some reason Callback method can not read Current.User as it return null. And well... nothing really changed as for now.
If you have ever experienced something like that or can find an issue I would be so thankful since I wasted already over 2 days on that issue.
EDIT:
After some testing I found out variables works fine if I run Post method on my own. So the problem is with handling callback from CoinPayments. Is there a specific way to deal with this?

Delete Records from a database

I am trying to delete set of records under my ASP.NET Application - API Controller. Here is my code from API Controller:
public JsonResult Delete([FromBody]ICollection<ShoppingItemViewModel> vm)
{
if (ModelState.IsValid)
{
try
{
var items = Mapper.Map<IEnumerable<ShoppingItem>>(vm);
_repository.DeleteValues(items, User.Identity.Name);
return Json(null);
}
catch (Exception Ex)
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(null);
}
}
else
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(null);
}
}
And here is my AngularJS Controller part taking care of this:
$scope.RemoveItems = function () {
$scope.isBusy = true;
$http.delete("/api/items", $scope.items)
.then(function (response) {
if (response.statusText == "OK" && response.status == 200) {
//passed
for (var i = $scope.items.length - 1; i > -1; i--) {
if ($scope.items[i].toRemove == true) {
$scope.items.splice(i, 1);
}
}
}
}, function (err) {
$scope.errorMessage = "Error occured: " + err;
}).finally(function () {
$scope.isBusy = false;
});
}
For unknown reason, this works like a charm in my POST method but not in the Delete Method. I believe that the problem might be caused by the fact, that DELETE method only accepts Integer ID?
If that is the case, what is the correct way how to delete multiple items with one call?

selectNodes(), selectSingleNode() functions in crm 2013

Can anyone tell me what are the replacements for selectNodes(), selectSingleNode() functions in XrmServiceToolKit. and how to use them in crm 2013.
Regards,
Nagaraju
You can use these two methods below:
function selectNodes(node, XPathExpression) {
if (typeof (node.selectNodes) != "undefined") {
return node.selectNodes(XPathExpression);
}
else {
var output = [];
var XPathResults = node.evaluate(XPathExpression, node, _NSResolver, XPathResult.ANY_TYPE, null);
var result = XPathResults.iterateNext();
while (result) {
output.push(result);
result = XPathResults.iterateNext();
}
return output;
}
}
function selectSingleNodeText(node, xpathExpr) {
var x = selectSingleNode(node, xpathExpr);
if (_isNodeNull(x))
{ return null; }
if (typeof (x.text) != "undefined") {
return x.text;
}
else {
return x.textContent;
}
}
function _isNodeNull(node) {
if (node == null)
{ return true; }
if ((node.attributes.getNamedItem("i:nil") != null) && (node.attributes.getNamedItem("i:nil").value == "true"))
{ return true; }
return false;
}
The most recent update uses jQuery to make selections from XML documents to allow for non-Internet Explorer browsers. Make sure that you have the latest XrmServiceToolkit javascript library.

If I know the name of a function, is it possible to get its parameters?

Dart code:
void hello(String name) {
print(name);
}
main() {
var funcName = "hello";
// how to get the parameter `String name`?
}
Using the function name as a string, "hello", is it possible to get the parameter String name of the real function hello ?
You can use mirrors to do that.
import 'dart:mirrors';
void hello(String name) {
print(name);
}
main() {
var funcName = "hello";
// get the top level functions in the current library
Map<Symbol, MethodMirror> functions =
currentMirrorSystem().isolate.rootLibrary.functions;
MethodMirror func = functions[const Symbol(funcName)];
// once function is found : get parameters
List<ParameterMirror> params = func.parameters;
for (ParameterMirror param in params) {
String type = MirrorSystem.getName(param.type.simpleName);
String name = MirrorSystem.getName(param.simpleName);
//....
print("$type $name");
}
}
You get this information through reflection (which it is not yet fully completed):
library hello_library;
import 'dart:mirrors';
void main() {
var mirrors = currentMirrorSystem();
const libraryName = 'hello_library';
var libraries = mirrors.findLibrary(const Symbol(libraryName));
var length = libraries.length;
if(length == 0) {
print('Library not found');
} else if(length > 1) {
print('Found more than one library');
} else {
var method = getStaticMethodInfo(libraries.first, const Symbol('hello'));
var parameters = getMethodParameters(method);
if(parameters != null) {
for(ParameterMirror parameter in parameters) {
print('name: ${parameter.simpleName}:, type: ${parameter.type.simpleName}');
}
}
}
}
MethodMirror getStaticMethodInfo(LibraryMirror library, Symbol methodName) {
if(library == null) {
return null;
}
return library.functions[methodName];
}
List<ParameterMirror> getMethodParameters(MethodMirror method) {
if(method == null) {
return null;
}
return method.parameters;
}
void hello(String name) {
print(name);
}

Resources