How to pass a list from method to another method - c#

How to pass below action to another action in order to export it in excel sheet
,I need to pass VL list to another action
public ActionResult Details(int S)
{
SLMEntitiesDB dbContext = new SLMEntitiesDB();
var VL = (from U in dbContext.Users
join P in dbContext.Products
on U.PID equals P.PID
where P.PID == U.PID
select new UP()
{
UserO = U,
ProductO = P
}).Where(U => U.UserO.LID == S).ToList();
TempData["Exc"] = VL;
return View(VL);
}
and the other action within the same controller, but it's not working
public void ExportToExcel()
{
var V = TempData["Exc"] as List;
ExcelPackage pck = new ExcelPackage();
ExcelWorksheet ws = pck.Workbook.Worksheets.Add("Report");
ws.Cells["A1"].Value = "UserName";
int rowStart = 1;
foreach (var item in V)// here is the error
{
ws.Cells[string.Format("A{0}", rowStart)].Value = item.UserO.CN;

you'll create another Function\Action on your controller and pass the data from your view to it. Depending on the size of the data, you could do that as a QueryString (note: type .ToString() considerations, html encoding in that approach), but it's more likely you'll store the instance server-side, using TempData[key] or something similar.
The other aspect of what you're attempting to do (export an Excel File) will be handled by the added Action; However, instead of you handling the entire Response writing in the scope of your action, I recommend you define a type that inherits the FileResult type - where you handle HttpResponseBase in the overloaded WriteFile function (example below).
XLSFileResult
This sample type will actually be writing Comma Separate Value (CSV) content, but the Content-Type (coupled with Content-Disposition) will 'indicate' to the client that it is an excel file - the Response will respond with an ".xls" file.
Note: the filename and extension in this sample are actually defined at it's initialization - in the action of the controller.
public class XLSFileResult : FileResult
{
public XLSFileResult() : base(#"application/vnd.ms-excel")
{
Data = new List<UP>();
}
public IEnumerable<UP> Data { get; set; }
protected override void WriteFile(HttpResponseBase response)
{
// note: you'll want to handle this better; I'm just choosing a property of each complex type.
string[] lines = Data.Select(d => string.Join(", ", d.UserO.UserName , d.ProductO.PName)).ToArray();
byte[] buffer = response.ContentEncoding.GetBytes(string.Join(Environment.NewLine, lines));
response.BinaryWrite(buffer);
}
}
Sample Action\Function on the Controller
public ActionResult Details(int S)
{
SLMEntitiesDB dbContext = new SLMEntitiesDB();
var VL = (from U in dbContext.Users
join P in dbContext.Products
on U.PID equals P.PID
where P.PID == U.PID
select new UP()
{
UserO = U,
ProductO = P
}).Where(U => U.UserO.LID == S).ToList();
return View(VL);
}
protected FileResult HandleDataToFileResult(IEnumerable<UP> data)
{
return new XLSFileResult()
{
Data = data,
FileDownloadName = "MyFile.xls" //by virtue of this assignment, a 'Content-Disposition' Response.Header is added to HttpResponseBase
};
}
public FileResult GenerateFile()
{
var data = (IEnumerable<UP>)TempData["GenerateFile"];
return HandleDataToFileResult(data);
}
Razor Page
In this sample of the razor page, we'll use a ActionLink...
#using SLMDemo0.Models
#model IEnumerable<UP>
#{
ViewBag.Title = "Details";
//Review TempData, it's session data that clears at the end of the next request
TempData["GenerateFile"] = Model.ToArray();
}
...
#Html.ActionLink("GenerateFile", "GenerateFile");

Related

ASP.NET MVC - Xml Export - formatting the file name according to class attributes

I have this class, which takes the selected file in the grid
[HttpPost]
public ActionResult ExportXml(string apontamentos)
{
try
{
string[] arrApontamentos = apontamentos.Split(';');
var listApontamentoId = arrApontamentos.Select(x => new Guid(x)).ToList();
var apontamentosViewModel = this._apontamentoAppService.ObterTodos(listApontamentoId);
List<ApontamentoExportarViewModel> listXml = new List<ApontamentoExportarViewModel>();
int item = 1;
foreach (var informacaoApontamentoVM in apontamentosViewModel)
{
listXml.Add(new ApontamentoExportarViewModel
{
Item = item,
Equipamento = informacaoApontamentoVM.Barco.SapId,
Atendimento = informacaoApontamentoVM.Atendimento,
Escala = informacaoApontamentoVM.LocalDaOperacao.Abreviacao,
DescricaoDaOperacao = informacaoApontamentoVM.CodigosDeOperacao.Descricao,
//GrupoDeCodigo = "xxx",
CodigoOperacao = informacaoApontamentoVM.CodigosDeOperacao.Codigo,
DataInicial = string.Format("{0:dd.MM.yyyy}", informacaoApontamentoVM.DataInicio),
HoraInicial = string.Format("{0:HH.mm.ss}", informacaoApontamentoVM.DataInicio),
DataFinal = string.Format("{0:dd:MM:yyyy}", informacaoApontamentoVM.DataTermino),
HoraFinal = string.Format("{0:HH:mm:ss}", informacaoApontamentoVM.DataTermino),
Observacoes = informacaoApontamentoVM.Observacao
});
item++;
}
var status = this._apontamentoAppService.ObterDescricaoStatusApontamento(Domain.Apontamentos.StatusApontamento.Exportado);
this._apontamentoAppService.AtualizarStatus(apontamentosViewModel.Select(x => x.Id).ToList(), status);
return new XmlActionResult<ApontamentoExportarViewModel>(listXml);
}
catch (Exception ex)
{
throw ex;
}
}
And a i have that other one, which does export and xml format and filename
public class XmlActionResult<T> : ActionResult
{
public XmlActionResult(List<T> data)
{
Data = data;
}
public List<T> Data { get; private set; }
public override void ExecuteResult(ControllerContext context)
{
context.HttpContext.Response.ContentType = "text/xml";
// TODO: Use your preferred xml serializer
// to serialize the model to the response stream :
// context.HttpContext.Response.OutputStream
ApontamentoExportarViewModel apontamentoExportarViewModel = new ApontamentoExportarViewModel();
var cd = new System.Net.Mime.ContentDisposition
{
// for example foo.bak
FileName = string.Format("MA_"+ "Equipamento" + "_{0:dd-MM-yyyy_HH-mm-ss}.xml", DateTime.Now),
// always prompt the user for downloading, set to true if you want
// the browser to try to show the file inline
Inline = false,
};
var root = new XmlRootAttribute("meadinkent");
XmlSerializer x = new XmlSerializer(Data.GetType(), root);
context.HttpContext.Response.AppendHeader("Content-Disposition", cd.ToString());
x.Serialize(context.HttpContext.Response.OutputStream, Data);
}
}
}
Basically, I need to get the "Equipamento" attribute and insert it into the file name.
The information from the "ApontamentoExportarViewModel" class is coming from the "Data" attribute, but how do you find the information inside that list? Remembering that I only need the information of the attribute "Equipment"
How would I bring the value of this attribute to the XmlActionResult class?
Well, you've got it in Data in the XmlActionResult, but because it's a List<T>, it could be anything. In this case, it's your ApontamentoExportarViewModel view model.
Should this XmlActionResult method be able to work with various kinds of objects, or only with ApontamentoExportarViewModel? If with various types, then not every one of those types will have a Equipamento property. In that case, you would have to do something like:
var fileName = "default";
if(Data is List<ApontamentoExportarViewModel>)
{
var record = (Data as List<ApontamentoExportarViewModel>).FirstOrDefault(); // what should happen if there's more than one?
if (record != null)
fileName = record.Equipamento;
}
and then later:
FileName = string.Format("MA_"+ fileName + "_{0:dd-MM-yyyy_HH-mm-ss}.xml", DateTime.Now);
Or something like that.
If you are sure that every object that comes in to your method will have a Equipamento property, then you could create a base class from which you derive your view model classes that has Equipamento, or an interface, and then alter your method to not accept any type (<T>), but rather only classes that derive from the base class / implement the interface.

Incorrect Models passed to View MVC C# error

Can anyone help me correct the issue im having creating a view in MVC. Normally i just use Add/View and it scaffolds a view for me based upon my created method. The only problem is that this time i am creating a method to pass to view and i keep getting this error message
The model item passed into the dictionary is of type 'UserJob',
but this dictionary requires a model item of type
'System.Collections.Generic.IEnumerable`1[UserJob]'.
The Methods i have written are the following...
public ActionResult AddJob(string userCode)
{
var jobs = jobsClient.GetAlljobs();
var alljobsCode = (from s in jobs select s.jobCode).ToList();
var usersJobs = (from s in db.UserJobs
where s.userCode == userCode
select s.jobCode).ToList();
var jobsNeeded = alljobsCode.Except(usersJobs);
List<UserJobsDTO> list = listBuilder(jobs, jobsNeeded);
ViewBag.jobCode = new SelectList(list, "jobCode", "jobDescription");
var model = new UserJob { userCode = userCode };
return View("AddJob", model);
}
private List<UserJobsDTO> listBuilder(
jobsService.jobsDTO[] jobs, IEnumerable<string> jobsNeeded)
{
List<UserJobsDTO> d = new List<UserJobsDTO>();
var f = jobsNeeded.ToArray();
var a = jobs.ToArray();
for (int i = 0; i < f.Length; i++)
{
d.Add(new UserJobsDTO()
{
jobCode = f.ElementAt(i),
description = a[i].jobDescription
});
}
return d;
}
When im debugging all of the required data is being passed to all the correct variable i am declaring, but the view just isnt playing ball. I was under the impression that scaffolding would automatically generate a useable View for me in Razor?? But this method just want play. Can anyone point me in the right direction??
Corrected version
public ActionResult AddJob(string userCode)
{
var jobs = jobsClient.GetAlljobs();
var alljobsCode = (from s in jobs select s.jobCode).ToList();
var usersJobs = (from s in db.UserJobs
where s.userCode == userCode
select s.jobCode).ToList();
var jobsNeeded = alljobsCode.Except(usersJobs);
List<UserJobsDTO> list = listBuilder(jobs, jobsNeeded);
ViewBag.jobCode = new SelectList(list, "jobCode", "jobDescription");
// var model = new UserJob { userCode = userCode };
return View("AddJob", usersJobs );
}
you will need to pass ienumarable here not an object type.
Update
#model IEnumerable<UserJobs>
foreach(var item in Model){
<span>#item.JobId</span>
<span>#item.JobName</span>
}

Cannot assign a void to an implicitly-typed local variable using Entity Framework 6

I am using a WCF refrence to call the last row from my Quote table. Now I wrote this method in my WCF application to get the last row, but I do not know it it works or not(I am trying to test it):
public void GetLastQuote()
{
using (TruckDb db = new TruckDb())
{
var quote = (from qData in db.Quotes
where qData.Id == qData.RepresetativeId
orderby qData.Id descending
select qData).First();
}
}
In my WPF application I am using the WCF reference and calling on the GetLastQuoteAsync() method, but it is giving me the following error:
Cannot assign void to an implicitly-typed local variable
And here is the method in my WPF application where I am trying to call the GetLastQuoteAsync() reference.
private async void wListOfBills_Loaded(object sender, RoutedEventArgs e)
{
using (TruckServiceClient client = new TruckServiceClient())
{
var quote = await client.GetLastQuoteAsync(); // -> This is where the error lies.
var bills = await client.GetListOfBillsAsync(quote.Item.Id);
if (bills == null)
{
dgFloor.IsEnabled = true;
return;
}
dgFloor.ItemsSource = bills.Select(x => new ListOfBillsView
{
Code = x.StockCode,
Group = x.GroupName,
Description = x.StockDescription,
Qty = x.Quantity,
Length = x.Length,
Width = x.Width,
Weight = x.Weight,
Price_m = x.PricePerMeter,
Cost = x.Cost,
Section = x.TruckSection.ToString()
}).ToList();
}
}
I have seen some people with the same question, but I do not fully understand how to implement the solutions in my own problem. If anyone could help, I would appreciate it allot! :)
You want to call what your query is returning, but the method wrapping around that query is returning nothing, because its type is void.
I assume you want to return an object of type Quote, so you need to change your method to this:
//change from void to Quote
public Quote GetLastQuote()
{
using (TruckDb db = new TruckDb())
{
var quote = (from qData in db.Quotes
where qData.Id == qData.RepresetativeId
orderby qData.Id descending
select qData).First();
//new
return quote;
}
}
Also GetLastQuote() is not the same as GetLastQuoteAsync() Have you posted the wrong method, which would throw the same error?
If there is also async version of this method it should probably look similar to this:
public async Task<Quote> GetLastQuote()
{
using (TruckDb db = new TruckDb())
{
var quote = (from qData in db.Quotes
where qData.Id == qData.RepresetativeId
orderby qData.Id descending
select qData).FirstAsync(); /*Note async method here*/
//new
return await quote;
}
}

Save HttpPostedFileBase temporary

I have a input of type file that is sending a HttpPostedFileBase (Excel.xlxs) to my controller. This file do I need to save temporary to use in another action. This HttpPostedFileBase am I converting to DataSet using Excel Data Reader. This works fine when I work directly with the file, but not when I have stored it in TempData.
First action:
[HttpPost]
public ActionResult CompareExcel(ExcelModel model, string submitValue, string compareOption)
{
TempData["firstFile"] = model.Files[0];
TempData["secondFile"] = model.Files[1];
if (submitValue == "Compare calculations")
{
var firstFile = TempData["firstFile"];
var secondFile = TempData["secondFile"];
if (firstFile == null || secondFile == null)
return View("CompareExcel");
else
return CompareColumn(compareOption);
}
//Assume submitValue is "Compare calculations"
}
Second action:
[HttpPost]
public ActionResult CompareColumn(string compareOption)
{
List<Calculation> cList = new List<Calculation>();
Calculation calc = new Calculation();
BigModel m = new BigModel();
HttpPostedFileBase firstFile = (HttpPostedFileBase)TempData["firstFile"];
HttpPostedFileBase secondFile = (HttpPostedFileBase)TempData["secondFile"];
DataSet firstSet = ExcelToDataSet.ConvertToDataSet(firstFile);
DataSet secondSet = ExcelToDataSet.ConvertToDataSet(secondFile);
for (var i = 0; i < firstSet.Tables[0].Rows.Count; i++) //Get Object reference not set to an instance of an object
{
DataRow data = firstSet.Tables[0].Rows[i];
calc.PresentValue = Convert.ToDecimal(data.Table.Rows[i]["Capital balance"]);
}
return View();
}
My model:
public partial class GetExcel
{
public List<HttpPostedFileBase> Files { get; set; }
public GetExcel()
{
Files = new List<HttpPostedFileBase>();
}
}
My method to convert my HttpPostedFileBase (Excel.xlxs) to DataSet. The method is working when sending the file directly but not when using TempData:
public static DataSet ConvertToDataSet(HttpPostedFileBase excelFile)
{
DataSet result = null;
if (excelFile != null && excelFile.ContentLength > 0)
{
// .xlsx
IExcelDataReader reader = ExcelReaderFactory.CreateOpenXmlReader(excelFile.InputStream);
// .xls
//IExcelDataReader reader = ExcelReaderFactory.CreateBinaryReader(file.InputStream);
reader.IsFirstRowAsColumnNames = true; // if your first row contains column names
result = reader.AsDataSet();
reader.Close();
}
return result;
}
When I debug and look at firstFile and secondFile I can see there is something there. I can see the filename of the HttpPostedFileBase but when I use ConvertToDataSet it fails in the first if. So obviously it's something wrong with the file saved in TempData. Is it possible to make this work with TempData or can someone suggest some easy way to go around this? Should it work and I'm doing something wrong? The whole thing is that the HttpPostedFileBase somehow needs to be saved temporary (in a easy way).

use one action of controller into another action

I want to use one action into another action for getting some values as:
[HttpPost]
public ActionResult Playlist(PageInfo p, long ID)
{
//long playid=Convert.ToInt64(p.Where);
var q = from client in my.Clients(0, 0)
join pl in db.Playlists on client.ClientId equals pl.ClientId
select new SimpleViewModel
{
Sequence=pl.PlaylistContentSequenceId,
PlaylistID = pl.PlaylistId,
PlaylistContentID=pl.ContentId
};
return Json(q.ToPage(p, "Sequence"), JsonRequestBehavior.DenyGet);
}
[HttpPost]
public ActionResult Save(List<ItemEditViewModel> data,long playlistid, List<long> deleted,string Title)
{
var playlist = db.Playlists.Include("PlaylistContents").FirstOrDefault(x => x.PlaylistId == playlistid);
for (int i = 0; i < playlist.PlaylistContents.Count; i++)
{
if(deleted.IndexOf(playlist.PlaylistContents[i].PlaylistContentId)>-1){
playlist.PlaylistContents.Remove(playlist.PlaylistContents[i]);
}
}
db.SaveChanges();
long ID=playlistid;
return Playlist(new PageInfo(),ID);
}
as you have seen in the code that after saving the contents into the database, the Playlist controller should be used for returning the Json data.
instead of
return Playlist(new PageInfo(),ID);
try
return RedirectToAction("Playlist", new {p = new PageInfo(), ID = ID});

Categories