i have this two methods to look for an object in a list of products, but when i try to ask to select one object to see i get the index out of bounds array(sorry that some of the code is in spanish)
Public Producto BuscarProducto(int id,List<Producto> prod)
{
var productos = ObtenerProducto();
var p = (from producto in productos
where producto.Id == id
select producto).First();
return p;
}
public List<Producto> ObtenerProducto()
{
var datos = ObtenerLineas();
List<Producto> productos = new List<Producto>();
foreach (var item in datos)
{
string[] info = item.Split(',');
Producto producto = new Producto
{
Id = int.Parse(info[0]),
Nombre = info[1],
Precio = double.Parse(info[2]),
Categoria = info[3],
Detalle = info[4]
};
productos.Add(producto);
}
return productos;
}
Make sure that there are four "," in the string that you are trying to split.
Also it would be better to check if there are atleast 5 elements in the array. You could try replacing your Add code with this checking.
if (info != null && info.Length >= 5)
{
Producto producto = new Producto
{
Id = int.Parse(info[0]),
Nombre = info[1],
Precio = double.Parse(info[2]),
Categoria = info[3],
Detalle = info[4]
};
productos.Add(producto);
}
Related
I need to sort the PROMEDIOCAL field in descending order but when implementing the sort it doesn't work. It lists me correctly by ID and I can also search by DISTRICT but I cannot sort the PROMEDIOCAL field in descending order when clicking on the header in the table
Controller:
public ActionResult ListarProfxServicio(int id, string CadenaBusqueda, string Orden)
{
List<TB_Profesionales> lista = new List<TB_Profesionales>();
ViewBag.cal = String.IsNullOrEmpty(Orden) ? "cod_asc" : "";
var data = from c in db.TB_Profesionales where c.IDSERVICIO == id select new {c.IDUSUARIO, c.NOMBRE, c.APELLIDO, c.SEXO, c.DISTRITO, c.DESCRIPCIÓN, c.PROMEDIOCAL};
var data2 = from c in db.TB_Profesionales select c;
foreach (var pro in data)
{
TB_Profesionales p = new TB_Profesionales();
p.IDUSUARIO = pro.IDUSUARIO;
p.NOMBRE = pro.NOMBRE;
p.APELLIDO = pro.APELLIDO;
p.SEXO = pro.SEXO;
p.DISTRITO = pro.DISTRITO;
p.DESCRIPCIÓN = pro.DESCRIPCIÓN;
p.PROMEDIOCAL = pro.PROMEDIOCAL;
lista.Add(p);
}
switch (Orden)
{
case "cod_asc":
data = data.OrderByDescending(s => s.PROMEDIOCAL);
break;
}
if (!String.IsNullOrEmpty(CadenaBusqueda))
{
data2 = data2.Where(s => s.DISTRITO.ToUpper().Contains(CadenaBusqueda.ToUpper()));
return View(data2.ToList());
}
return View(lista.ToList());
}
View:
<th>
#Html.ActionLink("Cod", "ListarProfxServicio", new {Orden = ViewBag.cal })
</th>
Problem
You are performing sorting in data but you are returning lista to the View. So your lista is never been sorted.
public ActionResult ListarProfxServicio(int id, string CadenaBusqueda, string Orden)
{
List<TB_Profesionales> lista = new List<TB_Profesionales>();
var data = from c in db.TB_Profesionales where c.IDSERVICIO == id select new {c.IDUSUARIO, c.NOMBRE, c.APELLIDO, c.SEXO, c.DISTRITO, c.DESCRIPCIÓN, c.PROMEDIOCAL};
...
foreach (var pro in data)
{
...
lista.Add(p);
}
switch (Orden)
{
case "cod_asc":
data = data.OrderByDescending(s => s.PROMEDIOCAL);
break;
}
...
return View(lista.ToList());
}
Solution
Change the below part to sort for lista.
switch (Orden)
{
case "cod_asc":
lista = lista.OrderByDescending(s => s.PROMEDIOCAL);
break;
}
Recommendation
The data and foreach part can be refactored together as:
List<TB_Profesionales> lista = from c in db.TB_Profesionales
where c.IDSERVICIO == id
select new TB_Profesionales
{
IDUSUARIO = c.IDUSUARIO,
NOMBRE = c.NOMBRE,
APELLIDO = c.APELLIDO,
SEXO = c.SEXO,
DISTRITO = c.DISTRITO,
DESCRIPCIÓN = c.DESCRIPCIÓN,
PROMEDIOCAL = c.PROMEDIOCAL
};
I'm trying to return two lists to my view, these lists help me fill some webgrid, I searched the web and I can not find a solution, I'm new to this
My Controller
public ActionResult Index()
{
List<WebGrid> list = new List<WebGrid>();
using (Web_INCAEntities dc = new Web_INCAEntities())
{
var v = (from a in dc.Cat_Proyecto
join b in dc.Cat_Pais on a.Id_Pais equals b.ID
join c in dc.Cat_estado on a.Id_Estado equals c.Id
select new WebGrid
{
ID = a.ID,
ID_kEY = a.ID_kEY,
Cliente = a.Cliente,
Tipo_servicio = a.Tipo_servicio,
Descripcion = a.Descripcion,
Contratista = a.Contratista,
INCA_PM = a.INCA_PM,
Importe_INCA = a.Importe_INCA,
Importe_Cliente = a.Importe_Cliente,
calle = a.calle,
colonia = a.colonia,
Estado = c.Estado,
Pais = b.Pais
});
list = v.ToList();
}
List<WebGrid> list_Usuario = new List<WebGrid>();
using (Web_INCAEntities dc = new Web_INCAEntities())
{
var v = (from a in dc.Usuarios
select new WebGrid
{
Usuario = a.Usuario,
nombres = a.Nombres,
apellidos = a.Apellido_Paterno,
empresa = a.Area_Empresa,
estatus_Usuario = a.Estatus,
alcance = a.Id_Alcance
});
list_Usuario = v.ToList();
}
return View("../Admin/Administrador", list, list_Usuario);
}
in the return View tried to return to the view and my two lists to fill two web grid, only that I get an error, but I want to know how together these two lists so I can fill my grid
As both the list are of same type i.e List<WebGrid>
you can use AddRange and concat both the list and pass to view
public ActionResult Index()
{
List<WebGrid> list = new List<WebGrid>();
using (Web_INCAEntities dc = new Web_INCAEntities())
{
var v = (from a in dc.Cat_Proyecto
join b in dc.Cat_Pais on a.Id_Pais equals b.ID
join c in dc.Cat_estado on a.Id_Estado equals c.Id
select new WebGrid
{
ID = a.ID,
ID_kEY = a.ID_kEY,
Cliente = a.Cliente,
Tipo_servicio = a.Tipo_servicio,
Descripcion = a.Descripcion,
Contratista = a.Contratista,
INCA_PM = a.INCA_PM,
Importe_INCA = a.Importe_INCA,
Importe_Cliente = a.Importe_Cliente,
calle = a.calle,
colonia = a.colonia,
Estado = c.Estado,
Pais = b.Pais
});
list = v.ToList();
}
List<WebGrid> list_Usuario = new List<WebGrid>();
using (Web_INCAEntities dc = new Web_INCAEntities())
{
var v = (from a in dc.Usuarios
select new WebGrid
{
Usuario = a.Usuario,
nombres = a.Nombres,
apellidos = a.Apellido_Paterno,
empresa = a.Area_Empresa,
estatus_Usuario = a.Estatus,
alcance = a.Id_Alcance
});
list_Usuario = v.ToList();
}
list.AddRange(list_Usuario);
return View("../Admin/Administrador", list);
}
or else you can create a class and use it
public class WebGridModel
{
public List<WebGrid> List1{get;set;}
public List<WebGrid> List2{get;set;}
}
and use it like this
public ActionResult Index()
{
List<WebGrid> list = new List<WebGrid>();
using (Web_INCAEntities dc = new Web_INCAEntities())
{
var v = (from a in dc.Cat_Proyecto
join b in dc.Cat_Pais on a.Id_Pais equals b.ID
join c in dc.Cat_estado on a.Id_Estado equals c.Id
select new WebGrid
{
ID = a.ID,
ID_kEY = a.ID_kEY,
Cliente = a.Cliente,
Tipo_servicio = a.Tipo_servicio,
Descripcion = a.Descripcion,
Contratista = a.Contratista,
INCA_PM = a.INCA_PM,
Importe_INCA = a.Importe_INCA,
Importe_Cliente = a.Importe_Cliente,
calle = a.calle,
colonia = a.colonia,
Estado = c.Estado,
Pais = b.Pais
});
list = v.ToList();
}
List<WebGrid> list_Usuario = new List<WebGrid>();
using (Web_INCAEntities dc = new Web_INCAEntities())
{
var v = (from a in dc.Usuarios
select new WebGrid
{
Usuario = a.Usuario,
nombres = a.Nombres,
apellidos = a.Apellido_Paterno,
empresa = a.Area_Empresa,
estatus_Usuario = a.Estatus,
alcance = a.Id_Alcance
});
list_Usuario = v.ToList();
}
var returnObj = new WebGridModel
{
List1= list;
List2=list_Usuario ;
}
return View("../Admin/Administrador", returnObj );
}
I am getting the list of Invoice details by Invoice Id.
Now i want to update AmountDue by respective Invoice Id.
i tried by below code:
ByInvoiceId.AmountDue = Convert.ToDecimal(100.00);
public_app_api.Invoices.Update(ByInvoiceId);
but..Error as
"A validation exception occurred"
What's the reason behind and How to solve this?
There are a number of ways to change the amount due on an invoice, however changing the value of the property directly is not one of them.
The amount due on an invoice is driven by the totals of the line items on the invoice minus the total of payments and allocated credit. One way to change the amount due is to change the values of your line items or add/remove some line items. You won't be able to change the invoice if it has been paid/partially paid.
Another way you could change the amount due on an invoice is to add a payment against the invoice or allocate credit from a credit note, prepayment, or overpayment to the invoice
In addition to MJMortimer's answer.
You can't change the line amounts on an AUTHORISED invoice via the c# API. You have to VOID the invoice and create a new one. You can however update DRAFT and SUBMITTED ones by updating the line items.
EDIT: Here is some code to help you. This is create invoice code, but amending one is essentially the same.
public XeroTransferResult CreateInvoices(IEnumerable<InvoiceModel> invoices, string user, string status)
{
_user = XeroApiHelper.User(user);
var invoicestatus = InvoiceStatus.Draft;
if (status == "SUBMITTED")
{
invoicestatus = InvoiceStatus.Submitted;
}
else if (status == "AUTHORISED")
{
invoicestatus = InvoiceStatus.Authorised;
}
var api = XeroApiHelper.CoreApi();
var xinvs = new List<Invoice>();
foreach (var inv in invoices)
{
var items = new List<LineItem>();
foreach (var line in inv.Lines)
{
decimal discount = 0;
if (line.PriceBeforeDiscount != line.Price)
{
discount = (decimal)(1 - line.Price / line.PriceBeforeDiscount) * 100;
}
items.Add(new LineItem
{
AccountCode = line.AccountCode,
Description = line.PublicationName != "N/A" ? line.PublicationName + " - " + line.Description : line.Description,
TaxAmount = (decimal)line.TaxAmount,
Quantity = 1,
UnitAmount = (decimal)line.PriceBeforeDiscount,
DiscountRate = discount,
TaxType = line.XeroCode,
ItemCode = line.ItemCode
});
}
var person = inv.Company.People.FirstOrDefault(p => p.IsAccountContact);
if (person == null)
{
person = inv.Company.People.FirstOrDefault(p => p.IsPrimaryContact);
}
var ninv = new Invoice
{
Number = inv.ClientInvoiceId,
Type = InvoiceType.AccountsReceivable,
Status = invoicestatus,
Reference = inv.Reference,
Contact = new Contact
{
Name = inv.Company.OrganisationName,
//ContactNumber = "MM" + inv.Company.CompanyId.ToString(),
FirstName = person.FirstName,
LastName = person.LastName,
EmailAddress = person.Email,
Phones = new List<Phone>()
{
new Phone {PhoneNumber = person.Telephone, PhoneType = PhoneType.Default},
new Phone {PhoneNumber = person.Mobile, PhoneType = PhoneType.Mobile}
},
Addresses = new List<Address>
{ new Address
{
//AttentionTo = inv.Company.People.FirstOrDefault(p => p.IsAccountContact) == null
//? inv.Company.People.FirstOrDefault(p=> p.IsPrimaryContact).FullName
//: inv.Company.People.FirstOrDefault(p => p.IsAccountContact).FullName,
//AddressLine1 = inv.Company.OrganisationName,
AddressLine1 = inv.Company.Address.Address1,
AddressLine2 = inv.Company.Address.Address2 ?? "",
AddressLine3 = inv.Company.Address.Address3 ?? "",
Region = inv.Company.Address.CountyState,
City = inv.Company.Address.TownCity,
PostalCode = inv.Company.Address.PostCode,
}
}
},
AmountDue = (decimal)inv.TotalAmount,
Date = inv.InvoiceDate,
DueDate = inv.DueDate,
LineItems = items,
LineAmountTypes = LineAmountType.Exclusive
};
if (SessionContext.TransferContactDetailsToXero == false)
{
ninv.Contact = new Contact
{
Id = inv.Company.XeroId ?? Guid.Empty,
Name = inv.Company.OrganisationName
};
}
xinvs.Add(ninv);
}
var success = true;
var xinvresult = new List<Invoice>();
try
{
api.SummarizeErrors(false);
xinvresult = api.Invoices.Create(xinvs).ToList();
}
catch (ValidationException ex)
{
// Something's gone wrong
}
foreach (var inv in xinvresult)
{
var mminvoice = invoices.FirstOrDefault(i => i.ClientInvoiceId == inv.Number);
if (inv.Errors != null && inv.Errors.Count > 0)
{
success = false;
if (mminvoice != null)
{
var errors = new List<XeroError>();
foreach (var err in inv.Errors)
{
errors.Add(new XeroError { ErrorDescription = err.Message });
}
mminvoice.XeroErrors = errors;
}
}
else
{
mminvoice.XeroTransferDate = DateTime.Now;
mminvoice.XeroId = inv.Id;
mminvoice.XeroErrors = new List<XeroError>();
}
}
return new XeroTransferResult
{
Invoices = invoices,
Success = success
};
}
Im using DTO's in EntityFrameWork with WebApi 2.0 , so I want to retrieve all the Orders, within the Orders, OrderProducts is a list in my program, I want to retrieve all the OrderProducts related to that Order my code right now is the following:
public async Task < IHttpActionResult > GetOrder() {
var order = from x in db.Order
select new OrderDTO {
OrderId = x.OrderId,
UserId = x.UserId,
orderStatusCode = x.orderStatusCode,
OrderProducts = new List < OrderProductDTO > {
new OrderProductDTO {
OrderId = x.OrderProducts.Select(y = >y.OrderId).FirstOrDefault(),
OrderProductId = x.OrderProducts.Select(y = >y.OrderProductId).FirstOrDefault(),
ProductId = x.OrderProducts.Select(y = >y.ProductId).FirstOrDefault(),
Product = new ProductDTO() {
productDesc = x.OrderProducts.Select(y = >y.Product.productDesc).FirstOrDefault(),
ProductId = x.OrderProducts.Select(y = >y.Product.ProductId).FirstOrDefault(),
productName = x.OrderProducts.Select(y = >y.Product.productName).FirstOrDefault(),
productPrice = x.OrderProducts.Select(y = >y.Product.productPrice).FirstOrDefault(),
}
}
},
purchaseDate = x.purchaseDate,
quantityOrder = x.quantityOrder,
totalOrderPrice = x.totalOrderPrice,
User = new UserDTO {
UserId = x.UserId,
username = x.User.username,
userInfo = new UserInfoDTO {
adress = x.User.UserInfo.adress,
city = x.User.UserInfo.city,
country = x.User.UserInfo.country,
zip = x.User.UserInfo.zip
}
}
};
return Ok(order);
Everything appears to be ok, but when I call the WebApi only the first element is returned, not all the elements in OrderProduct:
Any idea how to retrieve all the OrderProducts? Thanks.
Well you're only populating a single item in your query. Instead, you should do this:
....
OrderProducts = x.OrderProducts.Select(op => new OrderProductDTO
{
OrderId = op.OrderId,
OrderProductId = op.OrderProductId,
//etc
}
....
It looks like you're only asking for one Product instead of a List
Product = new ProductDTO() {
productDesc = x.OrderProducts.Select(y = >y.Product.productDesc).FirstOrDefault(),
ProductId = x.OrderProducts.Select(y = >y.Product.ProductId).FirstOrDefault(),
productName = x.OrderProducts.Select(y = >y.Product.productName).FirstOrDefault(),
productPrice = x.OrderProducts.Select(y = >y.Product.productPrice).FirstOrDefault(),
}
Should probably be
Products = new List<ProductDTO>() {...}
<?xml version="1.0" standalone="yes"?>
<CompanyInfo>
<Employee name="Jon" deptId="123">
<Region name="West">
<Area code="96" />
</Region>
<Region name="East">
<Area code="88" />
</Region>
</Employee>
</CompanyInfo>
public class Employee
{
public string EmployeeName { get; set; }
public string DeptId { get; set; }
public List<string> RegionList {get; set;}
}
public class Region
{
public string RegionName { get; set; }
public string AreaCode { get; set; }
}
I am trying to read this XML data, so far I have tried this:
XDocument xml = XDocument.Load(#"C:\data.xml");
var xElement = xml.Element("CompanyInfo");
if (xElement != null)
foreach (var child in xElement.Elements())
{
Console.WriteLine(child.Name);
foreach (var item in child.Attributes())
{
Console.WriteLine(item.Name + ": " + item.Value);
}
foreach (var childElement in child.Elements())
{
Console.WriteLine("--->" + childElement.Name);
foreach (var ds in childElement.Attributes())
{
Console.WriteLine(ds.Name + ": " + ds.Value);
}
foreach (var element in childElement.Elements())
{
Console.WriteLine("------->" + element.Name);
foreach (var ds in element.Attributes())
{
Console.WriteLine(ds.Name + ": " + ds.Value);
}
}
}
}
This enables me to get each node, its attribute name and value and so I can save these data into the relevant field in database, but this seems a long winded way and
not flexible, for instance if the XML structure changes all those foreach statements needs revisiting, also it is difficult to filter the data this way,
I need to write certain if statements to filter the data (e.g get employees from West only etc...)
I was looking for a more flexible way, using linq, something like this:
List<Employees> employees =
(from employee in xml.Descendants("CompanyInfo")
select new employee
{
EmployeeName = employee.Element("employee").Value,
EmployeeDeptId = ?? get data,
RegionName = ?? get data,
AreaCode = ?? get data,,
}).ToList<Employee>();
But I am not sure how I can get the values from the child nodes and apply the filtering (to get the certain employees only). Is this possible? Any help is appreciated.
Thanks
var employees = (from e in xml.Root.Elements("Employee")
let r = e.Element("Region")
where (string)r.Attribute("name") == "West"
select new Employee
{
EmployeeName = (string)e.Attribute("employee"),
EmployeeDeptId = (string)e.Attribute("deptId"),
RegionName = (string)r.Attribute("name"),
AreaCode = (string)r.Element("Area").Attribute("code"),
}).ToList();
But it will still require query revision when XML file structure changes.
Edit
Query for multiple regions per employee:
var employees = (from e in xml.Root.Elements("Employee")
select new Employee
{
EmployeeName = (string)e.Attribute("employee"),
DeptId = (string)e.Attribute("deptId"),
RegionList = e.Elements("Region")
.Select(r => new Region {
RegionName = (string)r.Attribute("name"),
AreaCode = (string)r.Element("Area").Attribute("code")
}).ToList()
}).ToList();
You can then filter the list for employees from given region only:
var westEmployees = employees.Where(x => x.RegionList.Any(r => r.RegionName == "West")).ToList();
You can track the structure:
from employee in xml
.Element("CompanyInfo") // must be root
.Elements("Employee") // only directly children of CompanyInfo
or less strictly
from employee in xml.Descendants("Employee") // all employees at any level
And then get the information you want:
select new Employee
{
EmployeeName = employee.Attribute("name").Value,
EmployeeDeptId = employee.Attribute("deptId").Value,
RegionName = employee.Element("Region").Attribute("name").Value,
AreaCode = employee.Element("Region").Element("Area").Attribute("code").Value,
}
And with the additional info about multiple regions, assuming a List<Region> Regions property:
select new Employee
{
EmployeeName = employee.Attribute("name").Value,
EmployeeDeptId = employee.Attribute("deptId").Value,
//RegionName = employee.Element("Region").Attribute("name").Value,
//AreaCode = employee.Element("Region").Element("Area").Attribute("code").Value,
Regions = (from r in employee.Elements("Region") select new Region
{
Name = r.Attribute("name").Value,
Code = r.Element("Area").Attribute("code").Value,
}).ToList();
}
You can do the selection in one query and then the filtering in second or combine them both to one query:
Two queries:
// do te transformation
var employees =
from employee in xml.Descendants("CompanyInfo").Elements("Employee")
select new
{
EmployeeName = employee.Attribute("name").Value,
EmployeeDeptId = employee.Attribute("deptId").Value,
Regions = from region in employee.Elements("Region")
select new
{
Name = region.Attribute("name").Value,
AreaCode = region.Element("Area").Attribute("code").Value,
}
};
// now do the filtering
var filteredEmployees = from employee in employees
from region in employee.Regions
where region.AreaCode == "96"
select employee;
Combined one query (same output):
var employees2 =
from selectedEmployee2 in
from employee in xml.Descendants("CompanyInfo").Elements("Employee")
select new
{
EmployeeName = employee.Attribute("name").Value,
EmployeeDeptId = employee.Attribute("deptId").Value,
Regions = from region in employee.Elements("Region")
select new
{
Name = region.Attribute("name").Value,
AreaCode = region.Element("Area").Attribute("code").Value,
}
}
from region in selectedEmployee2.Regions
where region.AreaCode == "96"
select selectedEmployee2;
But there is one little thing you should consider adding. For robustness, you need to check existence of your elements and attributes then the selection will look like that:
var employees =
from employee in xml.Descendants("CompanyInfo").Elements("Employee")
select new
{
EmployeeName = (employee.Attribute("name") != null) ? employee.Attribute("name").Value : string.Empty,
EmployeeDeptId = (employee.Attribute("deptId") != null) ? employee.Attribute("deptId").Value : string.Empty,
Regions = (employee.Elements("Region") != null)?
from region in employee.Elements("Region")
select new
{
Name = (region.Attribute("name")!= null) ? region.Attribute("name").Value : string.Empty,
AreaCode = (region.Element("Area") != null && region.Element("Area").Attribute("code") != null) ? region.Element("Area").Attribute("code").Value : string.Empty,
}
: null
};