I have been searching the internet for days now and I was just wondering if anyone has done any work with exporting data to excel using MVC 3. I really need a good tutorial that has step-by-step instructions on how to export excel data using MVC 3 with C#. I have found plenty of articles but none of them seem to work with my existing database. I am just looking for some instruction on where to put methods etc. This tutorial http://stephenwalther.com/blog/archive/2008/06/16/asp-net-mvc-tip-2-create-a-custom-action-result-that-returns-microsoft-excel-documents.aspx
seems to be highly recommended on stack overflow. I have followed the article's instructions to the letter but I can't run the program because Visual studio is throwing an error on the return for method GenerateExcel1
This is where VS is saying I have an error
return this.Excel(db, db.iamp_mapping, "data.xls")
right now I am getting 2 error messages that say
Error 1 'DBFirstMVC.Controllers.PaController' does not contain a
definition for 'Excel' and the best extension method overload
'DBFirstMVC.CustomActionResults.ExcelControllerExtensions.Excel(System.Web.Mvc.Controller,
System.Data.Linq.DataContext, System.Linq.IQueryable, string)' has
some invalid arguments C:\Documents and Settings\lk230343\My
Documents\Visual Studio 2010\WebSites\DBFirstMVC
Saves\DBFirstMVC_CRUD_and_PAGING_done\DBFirstMVC\Controllers\PaController.cs 193 24 DBFirstMVC
Error 2 Argument 2: cannot convert from 'DBFirstMVC.Models.PaEntities'
to 'System.Data.Linq.DataContext' C:\Documents and
Settings\lk230343\My Documents\Visual Studio 2010\WebSites\DBFirstMVC
Saves\DBFirstMVC_CRUD_and_PAGING_done\DBFirstMVC\Controllers\PaController.cs 193 35 DBFirstMVC
Has anyone ever seen these errors before or have any idea on how I can fix them? I mean the excel method exists in ExcelControllerExtensions.cs and I thought I had made that assembly available to the PaController. Honestly, I have no idea why it is throwing an error on the return so any advice/discussion/help would be welcomed. I have included the code for the 3 files that I have been messing with but if you think I forgot to post one that is needed to diagnose this error let me know and I will post it. Thanks for your help!
PaController
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Web.UI.WebControls;
using System.Web;
using System.Web.Mvc;
using DBFirstMVC.Models;
using System.Data;
using PagedList;
using PagedList.Mvc;
using DBFirstMVC.Controllers;
using System.IO;
using DBFirstMVC;
using DBFirstMVC.CustomActionResults;
namespace DBFirstMVC.Controllers
{
public class PaController : Controller
{
private PaEntities db = new PaEntities();
//
// GET: /Pa/
public ViewResult Index(string sortOrder, string currentFilter, string searchString, int? page)
{
ViewBag.CurrentSort = sortOrder;
ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "PA desc" : "";
ViewBag.MPSortParm = sortOrder == "MP" ? "MP desc" : "MP asc";
ViewBag.IASortParm = sortOrder == "IA" ? "IA desc" : "IA asc";
if (Request.HttpMethod == "GET")
{
searchString = currentFilter;
}
else
{
page = 1;
}
ViewBag.CurrentFilter = searchString;
var IAMP = from p in db.iamp_mapping select p;
if (!String.IsNullOrEmpty(searchString))
{
IAMP = IAMP.Where(p => p.PA.ToUpper().Contains(searchString.ToUpper()));
}
switch (sortOrder)
{
case "Pa desc":
IAMP = IAMP.OrderByDescending(p => p.PA);
break;
case "MP desc":
IAMP = IAMP.OrderByDescending(p =>p.MAJOR_PROGRAM);
break;
case "MP asc":
IAMP = IAMP.OrderBy(p =>p.MAJOR_PROGRAM);
break;
case "IA desc":
IAMP = IAMP.OrderByDescending(p => p.INVESTMENT_AREA);
break;
case "IA asc":
IAMP = IAMP.OrderBy(p => p.INVESTMENT_AREA);
break;
default:
IAMP = IAMP.OrderBy(p => p.PA);
break;
}
int pageSize = 25;
int pageNumber = (page ?? 1);
return View(IAMP.ToPagedList(pageNumber, pageSize));
}
//
// GET: /Pa/Details/5
public ActionResult Details(int id)
{
return View();
}
//
// GET: /Pa/Create
public ActionResult Create()
{
return View();
}
//
// POST: /Pa/Create
[HttpPost]
public ActionResult Create(iamp_mapping IAMP)
{
try
{
using (var db = new PaEntities())
{
db.iamp_mapping.Add(IAMP);
db.SaveChanges();
}
return RedirectToAction("Index");
}
catch
{
return View();
}
}
//
// GET: /Pa/Edit/5
public ActionResult Edit(string id)
{
using (var db = new PaEntities())
{
return View(db.iamp_mapping.Find(id));
}
}
//
// POST: /Pa/Edit/5
[HttpPost]
public ActionResult Edit(string id, iamp_mapping IAMP)
{
try
{
using (var db = new PaEntities())
{
db.Entry(IAMP).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("");
}
}
catch
{
return View();
}
}
//
// GET: /Pa/Delete/5
public ActionResult Delete(string id)
{
using (var db = new PaEntities())
{
return View(db.iamp_mapping.Find(id));
}
}
//
// POST: /Pa/Delete/5
[HttpPost]
public ActionResult Delete(string id, iamp_mapping IAMP)
{
try
{
using (var db = new PaEntities())
{
var vIAMP = db.iamp_mapping.Find(id);
db.Entry(vIAMP).State = EntityState.Deleted;
db.SaveChanges();
return RedirectToAction("Index");
}
}
catch (Exception e)
{
throw (e);
//return View();
}
}
public ActionResult GenerateExcel1()
{
using (var db = new PaEntities())
{
return this.Excel(db, db.iamp_mapping, "data.xls");
}
}
}
}
ExcelResult.cs
using System;
using System.Web.Mvc;
using System.Data.Linq;
using System.Collections;
using System.IO;
using System.Web.UI.WebControls;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Drawing;
namespace DBFirstMVC
{
public class ExcelResult : ActionResult
{
private DataContext _dataContext;
private string _fileName;
private IQueryable _rows;
private string[] _headers = null;
private TableStyle _tableStyle;
private TableItemStyle _headerStyle;
private TableItemStyle _itemStyle;
public string FileName
{
get { return _fileName; }
}
public IQueryable Rows
{
get { return _rows; }
}
public ExcelResult(DataContext dataContext, IQueryable rows, string fileName)
: this(dataContext, rows, fileName, null, null, null, null)
{
}
public ExcelResult(DataContext dataContext, string fileName, IQueryable rows, string[] headers)
: this(dataContext, rows, fileName, headers, null, null, null)
{
}
public ExcelResult(DataContext dataContext, IQueryable rows, string fileName, string[] headers, TableStyle tableStyle, TableItemStyle headerStyle, TableItemStyle itemStyle)
{
_dataContext = dataContext;
_rows = rows;
_fileName = fileName;
_headers = headers;
_tableStyle = tableStyle;
_headerStyle = headerStyle;
_itemStyle = itemStyle;
// provide defaults
if (_tableStyle == null)
{
_tableStyle = new TableStyle();
_tableStyle.BorderStyle = BorderStyle.Solid;
_tableStyle.BorderColor = Color.Black;
_tableStyle.BorderWidth = Unit.Parse("2px");
}
if (_headerStyle == null)
{
_headerStyle = new TableItemStyle();
_headerStyle.BackColor = Color.LightGray;
}
}
public override void ExecuteResult(ControllerContext context)
{
// Create HtmlTextWriter
StringWriter sw = new StringWriter();
HtmlTextWriter tw = new HtmlTextWriter(sw);
// Build HTML Table from Items
if (_tableStyle != null)
_tableStyle.AddAttributesToRender(tw);
tw.RenderBeginTag(HtmlTextWriterTag.Table);
// Generate headers from table
if (_headers == null)
{
_headers = _dataContext.Mapping.GetMetaType(_rows.ElementType).PersistentDataMembers.Select(m => m.Name).ToArray();
}
// Create Header Row
tw.RenderBeginTag(HtmlTextWriterTag.Thead);
foreach (String header in _headers)
{
if (_headerStyle != null)
_headerStyle.AddAttributesToRender(tw);
tw.RenderBeginTag(HtmlTextWriterTag.Th);
tw.Write(header);
tw.RenderEndTag();
}
tw.RenderEndTag();
// Create Data Rows
tw.RenderBeginTag(HtmlTextWriterTag.Tbody);
foreach (Object row in _rows)
{
tw.RenderBeginTag(HtmlTextWriterTag.Tr);
foreach (string header in _headers)
{
string strValue = row.GetType().GetProperty(header).GetValue(row, null).ToString();
strValue = ReplaceSpecialCharacters(strValue);
if (_itemStyle != null)
_itemStyle.AddAttributesToRender(tw);
tw.RenderBeginTag(HtmlTextWriterTag.Td);
tw.Write(HttpUtility.HtmlEncode(strValue));
tw.RenderEndTag();
}
tw.RenderEndTag();
}
tw.RenderEndTag(); // tbody
tw.RenderEndTag(); // table
WriteFile(_fileName, "application/ms-excel", sw.ToString());
}
private static string ReplaceSpecialCharacters(string value)
{
value = value.Replace("’", "'");
value = value.Replace("“", "\"");
value = value.Replace("”", "\"");
value = value.Replace("–", "-");
value = value.Replace("…", "...");
return value;
}
private static void WriteFile(string fileName, string contentType, string content)
{
HttpContext context = HttpContext.Current;
context.Response.Clear();
context.Response.AddHeader("content-disposition", "attachment;filename=" + fileName);
context.Response.Charset = "";
context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.Response.ContentType = contentType;
context.Response.Write(content);
context.Response.End();
}
}
}
ExcelControllerExtensions
using System;
using System.Web.Mvc;
using System.Data.Linq;
using System.Collections;
using System.Web.UI.WebControls;
using System.Linq;
namespace DBFirstMVC.CustomActionResults
{
public static class ExcelControllerExtensions
{
public static ActionResult Excel
(
this Controller controller,
DataContext dataContext,
IQueryable rows,
string fileName
)
{
return new ExcelResult(dataContext, rows, fileName, null, null, null, null);
}
public static ActionResult Excel
(
this Controller controller,
DataContext dataContext,
IQueryable rows,
string fileName,
string[] headers
)
{
return new ExcelResult(dataContext, rows, fileName, headers, null, null, null);
}
public static ActionResult Excel
(
this Controller controller,
DataContext dataContext,
IQueryable rows,
string fileName,
string[] headers,
TableStyle tableStyle,
TableItemStyle headerStyle,
TableItemStyle itemStyle
)
{
return new ExcelResult(dataContext, rows, fileName, headers, tableStyle, headerStyle, itemStyle);
}
}
}
Model1.context.cs
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
namespace DBFirstMVC.Models
{
public partial class PaEntities : DbContext
{
public PaEntities()
: base("name=PaEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<iamp_mapping> iamp_mapping { get; set; }
public DbSet<pa_mapping> pa_mapping { get; set; }
}
}
iamp_mapping.cs
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
namespace DBFirstMVC.Models
{
public partial class iamp_mapping
{
public string PA { get; set; }
public string MAJOR_PROGRAM { get; set; }
public string INVESTMENT_AREA { get; set; }
}
}
The reason for the error is right there in the message: cannot convert from 'DBFirstMVC.Models.PaEntities' to 'System.Data.Linq.DataContext. It means that you PaEntities type cannot be converted to System.Data.Linq.DataContext, therefore none of your Excel extension methods' signature matches the arguments you are passing.
What is your PaEntities type? Does it inherit from System.Data.Linq.DataContext?
Related
I am writing an ASP.NET Core Web API with .NET 5.0 as an exercise.
In MyController.cs there is the method DownloadZip(). Here, it should be possible for the client to download a zip file. By the way, I create a zip file because I did not achieve to transfer multiple pictures. That is the actual goal. Provisionally, the zip file is still stored in the picture folder. Of course, that should not happen either. I simply still have difficulties with web services and transferring zip files via them.
Anyway, in the line return File(fullName, "text/plain"); I get the following error message:
System.InvalidOperationException: No file provider has been configured to process the supplied file.
I found several threads on StackOverflow last Friday about how to transfer a zip file using a memory stream. When I do it this way, the browser shows the individual bytes, but no finished file has been downloaded.
Postings is a list(of post) with
using System;
using System.Collections.Generic;
namespace ImageRepository
{
public sealed class Posting
{
public DateTime CreationTime { get; set; }
public List<ImageProperties> Imageproperties { get; }
public Posting(DateTime creationTime, List<ImageProperties> imPr)
{
CreationTime = creationTime;
Imageproperties = imPr;
}
}
}
And Imageproperties is the following:
namespace ImageRepository
{
public sealed class ImageProperties
{
public string FullName { get; set; }
public string _Name { get; set; }
public byte[] DataBytes { get; set; }
public ImageProperties(string FullName, string Name, byte[] dataBytes)
{
this.FullName = FullName;
this._Name = Name;
this.DataBytes = dataBytes;
}
}
}
MyController.cs
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using ImageRepository;
using System.IO.Compression;
namespace WebApp2.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class MyController : ControllerBase
{
private readonly IImageTransferRepository imageRepository;
private readonly System.Globalization.CultureInfo Deu = new System.Globalization.CultureInfo("de-DE");
public MyController(IImageTransferRepository imageTransferRepository)
{
this.imageRepository = imageTransferRepository;
}
//––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
[HttpGet("WhatAreTheNamesOfTheLatestPictures")] // Route will be https://localhost:44355/api/My/WhatAreTheNamesOfTheLatestPictures/
public ActionResult GetNamesOfNewestPosting()
{
List<string> imageNames = this.imageRepository.GetImageNames();
if (imageNames.Count == 0)
{
return NoContent();
}
return Ok(imageNames);
}
//––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
[HttpGet("ImagesOfLatestPost")] //route will be https://localhost:44355/api/My/ImagesOfLatestPost
public ActionResult DownloadZip()
{
List<Posting> Postings = this.imageRepository.GetImages();
if (Postings is null || Postings.Count == 0)
{
return NoContent();
}
System.DateTime now = System.DateTime.Now;
string now_as_string = now.ToString("G", Deu).Replace(':', '-');
string folderPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyPictures);
string fullName = $"{folderPath}\\{now_as_string}.zip";
using (ZipArchive newFile = ZipFile.Open(fullName, ZipArchiveMode.Create))
{
for (int i = 0; i < Postings[0].Imageproperties.Count; i++)
{
newFile.CreateEntryFromFile(Postings[0].Imageproperties[i].FullName,
Postings[0].Imageproperties[i]._Name);
}
}
return File(fullName, "text/plain");
}
}
}
Edit June 20, 2022, 4:16 pm
Based on Bagus Tesa's comment, I wrote the following:
byte[] zip_as_ByteArray = System.IO.File.ReadAllBytes(fullName);
return File(zip_as_ByteArray, "application/zip");
The automatic download takes place, but I still have to rename the file by attaching (a) .zip so that Windows recognises it as a zip file.
Furthermore, there is still the problem that I am still creating the zip file on the hard disk (using (ZipArchive newFile = ZipFile.Open(fullName, ZipArchiveMode.Create))). How can I change this?
Thanks to the thread linked by Bagus Tesa, I can now answer my question. I have adapted a few things to my needs, see for-loop, because I have several images.
[HttpGet("ImagesOfLatestPost")] //route will be https://localhost:44355/api/My/ImagesOfLatestPost
public ActionResult DownloadZip()
{
List<Posting> Postings = this.imageRepository.GetImages();
if (Postings is null || Postings.Count == 0)
{
return NoContent();
}
byte[] compressedBytes;
using (var outStream = new System.IO.MemoryStream())
{
using (var archive = new ZipArchive(outStream, ZipArchiveMode.Create, true))
{
for (int i = 0; i < Postings[0].Imageproperties.Count; i++)
{
ZipArchiveEntry fileInArchive = archive.CreateEntry(Postings[0].Imageproperties[i]._Name, CompressionLevel.Optimal);
using System.IO.Stream entryStream = fileInArchive.Open();
using System.IO.MemoryStream fileToCompressStream = new System.IO.MemoryStream(Postings[0].Imageproperties[i].DataBytes);
fileToCompressStream.CopyTo(entryStream);
}
}
compressedBytes = outStream.ToArray();
}
return File(compressedBytes, "application/zip", $"Export_{System.DateTime.Now:yyyyMMddhhmmss}.zip");
}
So I'm trying to retrieve data from a database to display it in a table.
(This is a WebApi project). The idea is to go through all the prodactivity from the table whose status is 1. Put them in some list and return it.
To do this, I need to convert a TBL object to DAL. but here I am stuck. It is unable to perform a conversion and is therefore unwilling to return an object of a different type.
I tried to convert in all sorts of ways but it'S out of sync with the type in the controller.
This is my code: (do'nt look at the other functions. Look at the function getProductivityRequest at the end)
UserController.cs
using BL;
using DTO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Cors;
namespace WebApiSystem.Controllers
{
[EnableCors(origins: "*", headers: "*", methods: "*")]//SupportsCredentials = true
[RoutePrefix("api/User")]
public class UserController : ApiController
{
[HttpGet]
[Route("login/{email}/{pass}")]
public IHttpActionResult LogIn(string email, string pass)
{
UserDTO user = BL.UserService.LogIn(email, pass);
if (user != null)
return Ok(user);
return NotFound();
}
[Route("register")]
public IHttpActionResult Register(UserDTO user)
{
return NotFound();
}
[HttpPost]
[Route("productivity")]
public IHttpActionResult InsertProductivity([FromBody] ProductivityDTO p)
{
bool b = BL.UserService.InsertProductivity(p);
if (b)
return Ok(b);
return BadRequest();
}
[HttpGet]
[Route("getProductivityRequest")]
public IHttpActionResult GetProductivityRequest()
{
return Json(BL.UserService.GetProductivityRequest());
}
}
}
UserService.cs
using DAL;
using DTO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BL
{
public class UserService
{
public static UserDTO LogIn(string email, string pass)
{
using (Model2 db = new Model2())
{
UserTbl user = db.UserTbl.FirstOrDefault(u => u.UserEmail == email && u.UserPassLogin == pass);
if (user == null)
return null;
return CONVERTERS.UserConverter.ConvertUsertoDTO(user);
}
}
public static bool InsertProductivity(ProductivityDTO p)
{
using (Model2 db = new Model2())
{
//conver dal to dto
ProductivityTbl prod = BL.CONVERTERS.ProductivityConverter.ProductivityDal(p);
prod.ProductivityStatus = 1;
db.ProductivityTbl.Add(prod);
db.SaveChanges();
return true;
}
return false;
}
public static ProductivityDTO GetProductivityRequest()//Here I can not convert
{
using (Model2 db = new Model2())
{
List<ProductivityDTO> PList = new List<ProductivityDTO>();
foreach (var item in db.ProductivityTbl.ToList())
{
if(item.ProductivityStatus==1)
{
ProductivityDTO prod = BL.CONVERTERS.ProductivityConverter.ConvertProductivitytoDTO(item);
PList.Add(prod);
}
}
return (PList);//He's unable to return the object
}
}
}
}
ProductivityConverter.cs(if it's relevant...)
using DTO;
using DAL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BL.CONVERTERS
{
class ProductivityConverter
{
public static ProductivityDTO ConvertProductivitytoDTO(ProductivityTbl productivity) {
return new ProductivityDTO
{
ProductivyCode = productivity.ProductivyCode,
ProductivityNum = productivity.ProductivityNum,
ProductivityStatus = productivity.ProductivityStatus,
UserCode = productivity.UserCode,
Cmment = productivity.Cmment,
Date = productivity.Date
};
}
public static ProductivityTbl ProductivityDal(ProductivityDTO productivity)
{
return new ProductivityTbl
{
ProductivyCode = productivity.ProductivyCode,
ProductivityNum = productivity.ProductivityNum,
ProductivityStatus = productivity.ProductivityStatus,
UserCode = productivity.UserCode,
Cmment = productivity.Cmment,
Date = productivity.Date
};
}
}
}
If anyone knows of another way to transfer the data I would love ideas.
Thanks!
Your method returns a ProductivityDTO:
public static ProductivityDTO GetProductivityRequest()
...but you are trying to return PList which is a List<ProductivityDTO>.
Your method signature should be:
public static List<ProductivityDTO> GetProductivityRequest()
Although your comment suggests you can't change the method signature. In which case you need to return just one DTO. How you determine which one is up to you. But if it were just one with a ProductivityStatus of 1 then you could do:
public static ProductivityDTO GetProductivityRequest()//Here I can not convert
{
using (Model2 db = new Model2())
{
return BL.CONVERTERS.ProductivityConverter.ConvertProductivitytoDTO(db.ProductivityTbl.FirstOrDefault(p => p.ProductivityStatus == 1)));
}
}
Your function is defined to return a single ProductivityDTO.
But your function is building a List<ProductivityDTO> and returning that.
Change your function return type to a collection type, such as:
public static List<ProductivityDTO> GetProductivityRequest()
or
public static IEnumerable<ProductivityDTO> GetProductivityRequest()
Is there anyway to change the file extension on a csv download from mvcgrid? It downloads as .csv and i'd like .txt to stop my users from opening the contents in excel?
I can see there is a custom rendering engine, but that seems to offer file contents formats rather than the extension.
Thanks
Managed it via a customendering engine
using MVCGrid.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
namespace MVCGrid.Web.Models
{
public class TextExportEngine : IMVCGridRenderingEngine
{
public bool AllowsPaging
{
get { return false; }
}
public void PrepareResponse(HttpResponse httpResponse)
{
httpResponse.Clear();
httpResponse.ContentType = "text/comma-separated-values";
httpResponse.AddHeader("content-disposition", "attachment; filename=\"" + "export" + ".txt\"");
httpResponse.BufferOutput = false;
}
public void Render(MVCGrid.Models.RenderingModel model, MVCGrid.Models.GridContext gridContext, System.IO.TextWriter outputStream)
{
var sw = outputStream;
StringBuilder sbHeaderRow = new StringBuilder();
foreach (var col in model.Columns)
{
if (sbHeaderRow.Length != 0)
{
sbHeaderRow.Append(",");
}
sbHeaderRow.Append(Encode(col.Name));
}
sbHeaderRow.AppendLine();
sw.Write(sbHeaderRow.ToString());
foreach (var item in model.Rows)
{
StringBuilder sbRow = new StringBuilder();
foreach (var col in model.Columns)
{
var cell = item.Cells[col.Name];
if (sbRow.Length != 0)
{
sbRow.Append(",");
}
string val = cell.PlainText;
sbRow.Append(Encode(val));
}
sbRow.AppendLine();
sw.Write(sbRow.ToString());
}
}
private string Encode(string s)
{
if (String.IsNullOrWhiteSpace(s))
{
return "";
}
return s;
}
public void RenderContainer(MVCGrid.Models.ContainerRenderingModel model, System.IO.TextWriter outputStream)
{
}
}
}
and then adding the following to my grid definition
.AddRenderingEngine("tabs", typeof(TextExportEngine)
I have had a static version of this type of code working in a static version. However the API calls were just incredibly slow. I am trying to move to asynchronous now that C# 7 supports console async tasks (where I add code to connect to my DB and store data. I want to see this code output on the console to ensure it's working so I can assign variables for loading. I can't seem to figure out how to access the list from main. Here is the code I have so far:
Wrapper (or C# library):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace AlphaVantageApiWrapper
{
public static class AlphaVantageApiWrapper
{
public static async Task<AlphaVantageRootObject> GetTechnical(List<ApiParam> parameters, string apiKey)
{
var stringRequest = parameters.Aggregate(#"https://www.alphavantage.co/query?", (current, param) => current + param.ToApiString());
stringRequest += "&apikey=" + apiKey;
var apiData = await CallAlphaVantageApi(stringRequest);
var technicalsObject = new AlphaVantageRootObject
{
MetaData = new MetaData
{
Function = parameters.FirstOrDefault(x => x.ParamName.Equals("function"))?.ParamValue ?? "NA?",
Interval = parameters.FirstOrDefault(x => x.ParamName.Equals("interval"))?.ParamValue ?? "NA?",
SeriesType = parameters.FirstOrDefault(x => x.ParamName.Equals("series_type"))?.ParamValue ?? "NA?",
Symbol = parameters.FirstOrDefault(x => x.ParamName.Equals("symbol"))?.ParamValue ?? "NA?"
},
TechnicalsByDate = apiData.Last.Values().OfType<JProperty>().Select(x => new TechnicalDataDate
{
Date = Convert.ToDateTime(x.Name),
Data = x.Value.OfType<JProperty>().Select(r => new TechnicalDataObject
{
TechnicalKey = r.Name,
TechnicalValue = Convert.ToDouble(r.Value.ToString())
}).ToList()
})
.ToList()
};
return technicalsObject;
}
public class ApiParam
{
public string ParamName;
public string ParamValue;
public ApiParam(string paramNameIn, string paramValueIn)
{
ParamName = paramNameIn;
ParamValue = paramValueIn;
}
public string ToApiString()
{
return $"&{ParamName}={ParamValue}";
}
}
public static string ToDescription(this Enum enumeration)
{
var type = enumeration.GetType();
var memInfo = type.GetMember(enumeration.ToString());
if (memInfo.Length <= 0) return enumeration.ToString();
var attrs = memInfo[0].GetCustomAttributes(typeof(EnumDescription), false);
return attrs.Length > 0 ? ((EnumDescription)attrs[0]).Text : enumeration.ToString();
}
public static async Task<JObject> CallAlphaVantageApi(string stringRequest)
{
try
{
using (var client = new HttpClient())
{
var res = await client.GetStringAsync(stringRequest);
return JsonConvert.DeserializeObject<JObject>(res);
}
}
catch (Exception e)
{
//fatal error
return null;
}
}
public class AlphaVantageRootObject
{
public MetaData MetaData;
public List<TechnicalDataDate> TechnicalsByDate;
}
public class MetaData
{
public string Function;
public string Interval;
public string SeriesType;
public string Symbol;
}
public class TechnicalDataDate
{
public DateTime Date;
public List<TechnicalDataObject> Data;
}
public class TechnicalDataObject
{
public string TechnicalKey { get; set; }
public double TechnicalValue { get; set; }
}
public class EnumDescription : Attribute
{
public string Text { get; }
public EnumDescription(string text)
{
Text = text;
}
}
public enum AvFuncationEnum
{
[EnumDescription("SMA")] Sma,
[EnumDescription("EMA")] Ema,
[EnumDescription("MACD")] Macd,
[EnumDescription("STOCH")] Stoch,
[EnumDescription("RSI")] Rsi,
}
public enum AvIntervalEnum
{
[EnumDescription("1min")] OneMinute,
[EnumDescription("5min")] FiveMinutes,
[EnumDescription("15min")] FifteenMinutes,
[EnumDescription("30min")] ThirtyMinutes,
[EnumDescription("60min")] SixtyMinutes,
[EnumDescription("daily")] Daily,
[EnumDescription("weekly")] Weekly,
[EnumDescription("monthly")] Monthly
}
public enum AvSeriesType
{
[EnumDescription("close")] Close,
[EnumDescription("open")] Open,
[EnumDescription("high")] High,
[EnumDescription("low")] Low,
}
}
}
`
The c# async main task (which obviously isn't working)...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AlphaVantageApiWrapper.Test
{
public static class AlphaVantageApiDbLoader
{
public static async Task Main(string[] args)
{
var API_KEY = "EnterAPIHERE";
var StockTickers = new List<string> { "AAPL" }; //eventualy becomes a list pulled in from the DB for processing
foreach (var ticker in StockTickers)
{
var parameters = new List<AlphaVantageApiWrapper.ApiParam>
{
new AlphaVantageApiWrapper.ApiParam("function", AlphaVantageApiWrapper.AvFuncationEnum.Sma.ToDescription()),
new AlphaVantageApiWrapper.ApiParam("symbol", ticker),
new AlphaVantageApiWrapper.ApiParam("interval", AlphaVantageApiWrapper.AvIntervalEnum.Daily.ToDescription()),
new AlphaVantageApiWrapper.ApiParam("time_period", "5"),
new AlphaVantageApiWrapper.ApiParam("series_type", AlphaVantageApiWrapper.AvSeriesType.Open.ToDescription()),
};
//Start Collecting SMA values
var SMA_5 = await AlphaVantageApiWrapper.GetTechnical(parameters, API_KEY);
///var SMA_5Result = AlphaVantageApiWrapper.TechnicalDataObject() // can't all method error just want values fron list
parameters.FirstOrDefault(x => x.ParamName == "time_period").ParamValue = "20";
var SMA_20 = await AlphaVantageApiWrapper.GetTechnical(parameters, API_KEY);
parameters.FirstOrDefault(x => x.ParamName == "time_period").ParamValue = "50";
var SMA_50 = await AlphaVantageApiWrapper.GetTechnical(parameters, API_KEY);
parameters.FirstOrDefault(x => x.ParamName == "time_period").ParamValue = "200";
var SMA_200 = await AlphaVantageApiWrapper.GetTechnical(parameters, API_KEY);
//Change function to EMA
//Change function to RSI
//Change function to MACD
}
}
}
}
Any help would be greatly appreciated! I know the code runs in the background, I just can't seem to get it to a point to view it on the console screen. Eventually I would assign the symbol, date, value returned variable and read these to a DB. I'm used to using DataTables, but the async and .ToList is new to me. Thanks!!
Please help me with this error! Here ResultValue is an enumeration.
Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.
Compiler Error Message: CS0019: Operator '==' cannot be applied to operands of type 'string' and 'Answer.ResultValue'
Source Error:
Line 38: Answer a = (Answer)al[i];
Line 39:
Line 40: if (a.Result == Answer.ResultValue.Correct)
Line 41: correct=correct+1;
Line 42: }
=================================
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class results : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
ArrayList al = (ArrayList)Session["AnswerList"];
if (al == null)
{
Response.Redirect("History.aspx");
}
resultGrid.DataSource = al;
resultGrid.DataBind();
// Save the results into the database.
if (IsPostBack == false)
{
// Calculate score
double questions = al.Count;
double correct = 0.0;
for (int i = 0; i < al.Count; i++)
{
Answer a = (Answer)al[i];
if (a.Result == Answer.ResultValue.Correct)
correct=correct+1;
}
double score = (correct / questions) * 100;
SqlDataSource studentQuizDataSource = new SqlDataSource();
studentQuizDataSource.ConnectionString =
ConfigurationManager.ConnectionStrings["ConnectionString"].ToString();
studentQuizDataSource.InsertCommand = "INSERT INTO UserQuiz ([QuizID],
[DateTimeComplete], [Score], [UserName]) VALUES (#QuizID, #DateTimeComplete,
#Score, #UserName)";
studentQuizDataSource.InsertParameters.Add("QuizID",
Session["QuizID"].ToString());
studentQuizDataSource.InsertParameters.Add("Score", score.ToString());
studentQuizDataSource.InsertParameters.Add("UserName", User.Identity.Name);
studentQuizDataSource.InsertParameters.Add("DateTimeComplete",
DateTime.Now.ToString());
int rowsAffected = studentQuizDataSource.Insert();
if (rowsAffected == 0)
{
errorLabel.Text = "There was a problem saving your quiz results into our
database. Therefore, the results from this quiz will
not be displayed on the list on the main menu.";
}
}
}
protected void resultGrid_SelectedIndexChanged(object sender, EventArgs e)
{
SqlDataSource1.FilterExpression = "QuestionOrder=" + resultGrid.SelectedValue;
}
}
code for Answer.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class Answer : System.Web.UI.Page
{
private string m_QuestionID;
private string m_CorrectAnswer;
private string m_UserAns;
private string m_Result;
public string QuestionID
{
get
{
return m_QuestionID;
}
set
{
m_QuestionID = value;
}
}
public string CorrectAnswer
{
get
{
return m_CorrectAnswer;
}
set
{
m_CorrectAnswer = value;
}
}
public string UserAns
{
get
{
return m_UserAns;
}
set
{
m_UserAns = value;
}
}
public string Result
{
get
{
if (m_UserAns == m_CorrectAnswer)
{
return "Correct";
}
else
{
return "Incorrect";
}
}
}
public enum ResultValue
{
Correct,
Incorrect
}
}
It's pretty obvious you're trying to compare Enumeration Types with Strings, which aren't the same and can't be compared like that. Instead, I think you should try replacing this bit of code:
public string Result
{
get
{
if (m_UserAns == m_CorrectAnswer)
{
return "Correct";
}
else
{
return "Incorrect";
}
}
}
with
public ResultValue Result
{
get
{
if (m_UserAns == m_CorrectAnswer)
{
return ResultValue.Correct;
}
else
{
return ResultValue.Incorrect;
}
}
}
Try evaluating this :-
if (a.Result == Answer.ResultValue.Correct.ToString())