converting query to list (not working) asp.net mvc - asp.net

I am trying to create a query whose results will be stored in a ViewModel. When I try to assign the query variable to the ViewModel's method, I get the following error: "cannot implicitly convert type 'System.Linq.Iqueryable' to 'System.Collections.Generic.List'. An explicit-conversion exists (are you missing a cast?)".
I tried changing my ViewModel's methods to be of type Iqueryable instead of List which worked but then I couldn't use a foreach loop in my view to loop through my model so I changed it back to List. I tried doing ToList() after my query but that didn't work either. Any suggestions/hints/tips are greatly appreciated. Below is my controller code and my ViewModel code.
ViewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using KU_PLAN_DEV.Models;
namespace KU_PLAN_DEV.ViewModels
{
public class TrackViewModel
{
public List<string> TRACK_INFO { get; set; }
public List<string> GEN_ED_HEAD { get; set; }
}
}
Controller method:
public ActionResult DisplayTrackSheet(string trackButton)
{
var db = new KuPlanEntities();
var trackProgNum = (from info in db.TRACK_INFO
where info.degreeName == trackButton
select info.progNum).ToString();
var trackVerNum = (from info in db.TRACK_INFO
where info.degreeName == trackButton
select info.versionNum).ToString();
/*var queryTrack = (from tracks in db.GEN_ED_HEAD
where tracks.)*/
var trackData = (from trackInfo in db.TRACK_INFO
where trackInfo.progNum == trackProgNum
&& trackInfo.versionNum == trackVerNum
select trackInfo);
var trackDisplayMod = new TrackViewModel
{
TRACK_INFO = trackData
};
return View(trackDisplayMod);
}

var trackDisplayMod = new TrackViewModel
{
TRACK_INFO = trackData.ToList()
};
What error do you get when you make that change?

Related

Where to create SQLite DB and how to create a Select statement in any page

new to xamarin forms with SQLite. I need some guidance on how to use SQLite in Xamarin forms. Below is the code.
1) Create Interface
using System;
using SQLite.Net;
namespace SQLiteSample
{
public interface ISQLite
{
SQLiteConnection GetConnection();
}
}
2) Implementing ISQLite interface
using System;
using Xamarin.Forms;
using SQLiteEx.Droid;
using System.IO;
[assembly: Dependency(typeof(SqliteService))]
namespace SQLiteEx.Droid
{
public class SqliteService : ISQLite
{
public SqliteService() { }
public SQLite.Net.SQLiteConnection GetConnection()
{
var sqliteFilename = "myDB.db3";
// Documents folder
string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
var path = Path.Combine(documentsPath, sqliteFilename);
Console.WriteLine(path);
if (!File.Exists(path)) File.Create(path);
var plat = new SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid();
var conn = new SQLite.Net.SQLiteConnection(plat, path);
// Return the database connection
return conn;
}
}
}
3) Class for Database Operation :CRUD
using SQLite.Net;
using Xamarin.Forms;
namespace SQLiteEx
{
public class DataAccess
{
SQLiteConnection dbConn;
public DataAccess()
{
dbConn = DependencyService.Get<ISQLite>().GetConnection();
// create the table(s)
dbConn.CreateTable<Employee>();
}
public List<Employee> GetAllEmployees()
{
return dbConn.Query<Employee>("Select * From [Employee]");
}
public int SaveEmployee(Employee aEmployee)
{
return dbConn.Insert(aEmployee);
}
public int DeleteEmployee(Employee aEmployee)
{
return dbConn.Delete(aEmployee);
}
public int EditEmployee(Employee aEmployee)
{
return dbConn.Update(aEmployee);
}
}
}
I would like to know :
1) Where is the place to create a database that can be used through out the app. This means I can use it anywhere in any page without recreating it each time I need to use it.
2) Will table be recreated each time in above code?
3) How to I do a select statement in any page ie CustomerPage.xaml or SalesPage.xaml ?
In WinRT, I used below code. How to do it in Xamarin forms? Do I need to recreate SQLite DB? How to get the Path?
Using (var db = new SQLite.SQLiteConnection(App.DBPath){
var query = db.query<CashReceivable>("select * from CashRcvdTbl where Cust='" + Id + "'";
foreach( var item in query)
{
}
}
1) Here,
string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
This line in your ISQlite implementation points to your myDB.db3 SQLite file.
You can see this file into /data/data/#APP_PACKAGE_NAME#/files directory.
if (!File.Exists(path)) File.Create(path);
This line checks whether database file exists in above path or not. If not, then it creates this file once. This time it will be an empty sqlite file without any tables in it.
So, it will not recreated each time.
But, I think there is no need for this File exist check because, when you create a connection to the SQLite file, it automatically creates file if not exists.
So, it can be as simple as follows:
public class SqliteService : ISQLite
{
string dpPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), “myDB.db3”);
public SQLiteConnection GetConnection()
{
return new SQLiteConnection(new SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid(), dpPath, false);
}
}
2) Each time you create instance of DataAccess class, it will recreate Employee table/definition based on Table exists or not, as it calls dbConn.CreateTable<Employee>();
I generally write this line at Application Startup code.
public App ()
{
InitializeComponent ();
//Create all tables here. This will create them once when app launches.
using (var conn = DependencyService.Get<ISQLite>().GetConnection())
{
conn.CreateTable<Employee>();
}
MainPage = new HomePage ();
}
This will simply creates a new table in the SQLite file if table not exists, otherwise it updates the table definition.
3) You can do a select statement as follows:
public List<Employee> GetAllEmployees()
{
using (var conn = DependencyService.Get<ISQLite>().GetConnection())
{
return conn.Table<Employee>().ToList();
//OR
return conn.Query<Employee>("Select * From Employee");
}
}
In any page you can call this GetAllEmployees method to retrieve List of Employee.

String.Copy alternative for dotnet core

I'm trying to get the following code to work in dotnet core running on ubuntu linux - but getting a "string does not contain a definition for copy" compile error on this line - where apparently String.Copy is not supported in dotnet-core:
Attendance = String.Copy(markers) };
What are the best ways of doing a shallow string copy in dotnet Core? Should I use string.CopyTo?
Thanks
//I want to add an initial marker to each record
//based on the number of dates specified
//I want the lowest overhead when creating a string for each record
string markers = string.Join("", dates.Select(p => 'U').ToArray());
return logs.Aggregate( new List<MonthlyAttendanceReportRow>(), (rows, log) => {
var match = rows.FirstOrDefault(p => p.EmployeeNo == log.EmployeeNo);
if (match == null) {
match = new MonthlyAttendanceReportRow() {
EmployeeNo = log.EmployeeNo,
Name = log.FirstName + " " + log.LastName,
Attendance = String.Copy(markers) };
rows.Add(match);
} else {
}
return rows;
});
To complete Rogerson's answer, you can have an extension method which will do the exact thing that you are looking for.
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
namespace CSharp_Shell
{
public static class ext{
public static string Copy(this string val){
return new String(val.ToArray());
}
}
public static class Program
{
public static void Main()
{
string b = "bbb";
var a = b.Copy();
Console.WriteLine("Values are equal: {0}\n\nReferences are equal: {1}.", Object.Equals(a,b), Object.ReferenceEquals(a,b));
}
}
}
Try this:
string b = "bbb";
var a = new String(b.ToArray());
Console.WriteLine("Values are equal: {0}\n\nReferences are equal: {1}.", Object.Equals(a,b), Object.ReferenceEquals(a,b));
You can see it running on this fiddle.

Prevent Inserting same combination of Component and template :

In a page when we will click the component Presentation tab we can see the component and template listed there.On clicking of Insert button just below that, it will open another window "Insert component presentation" there also we will have Insert and close button.So now what i need to do While inserting i need to check whether the combination of selected Component and Template is already present there on page or not. If yes then it should prevent inserting the same with a popup like "this combination is already present, select other componet".
Any idea how can i proceed. How can i trigger a Javascript on the Insert button?
EDIT:
When i am subscrbing it to Page i am getting erro.My code :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Text;
using Tridion.ContentManager.Extensibility.Events;
using Tridion.ContentManager.Extensibility;
using Tridion.ContentManager.ContentManagement;
using System.IO;
using System.Windows.Forms;
namespace MyEventHandlers
{
[TcmExtension("MyEventHandlerExtension")]
public class MyEventHandler : TcmExtension
{
public MyEventHandler()
{
Subscribe();
}
public void Subscribe()
{
EventSystem.Subscribe<Page, SaveEventArgs>(SaveBtnInitiated, EventPhases.Initiated);
}
private void SaveBtnInitiated(Page subject, SaveEventArgs args, EventPhases phase)
{
try
{
List<string> allcplist = new List<string>();
List<string> allcplist = new List<string>();
foreach (ComponentPresentation cp in subject.ComponentPresentations)
{
allcplist.Add(cp.Component.Id + "," + cp.ComponentTemplate.Id);
}
List<string> uniquecplist = allcplist.Distinct().ToList();
if (allcplist.Count != uniquecplist.Count)
{
subject.Checkin(false);
throw new Exception("Page has duplicate component presentation");
}
catch(Exception)
{
}
}
You can implement this in an event handler that is subscribed to the Page Save event and the Initiated phase. When there is a duplicate Component Presentation you can cancel the Save by throwing an exception. The message will be shown in the Message Center in the TCM Explorer.
Why are you subscribing to the Component? I think it should be the Page. Then you can walk through the ComponentPresentations property.
Code to go through the Component Presentations and throw an exception when duplicate presentations are found:
foreach (var cpA in subject.ComponentPresentations)
{
if (subject.ComponentPresentations.Where(cpB => ComponentPresentationsAreEqual(cpA, cpB)).ToList().Count() > 2)
{
throw new DuplicateComponentPresentationsEmbeddedOnPageException();
}
}
And the function to include cpB in the list when it is equal to cpA:
function ComponentPresentationsAreEqual(ComponentPresentation cpA, ComponentPresentation cpB)
{
return cpA.Component.Id == cpB.Component.Id && cpA.ComponentTemplate.Id == cpB.ComponentTemplate.Id;
}
I got my Result with this code Thanks to #Arjen Stobbe
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Text;
using Tridion.ContentManager.Extensibility.Events;
using Tridion.ContentManager.Extensibility;
using Tridion.ContentManager.ContentManagement;
using System.IO;
using System.Windows.Forms;
namespace MyEventHandlers
{
[TcmExtension("MyEventHandlerExtension")]
public class MyEventHandler : TcmExtension
{
public MyEventHandler()
{
Subscribe();
}
public void Subscribe()
{
EventSystem.Subscribe<Page, SaveEventArgs>(SaveBtnInitiated, EventPhases.Initiated);
}
private void SaveBtnInitiated(Page subject, SaveEventArgs args, EventPhases phase)
{
try
{
List<string> allcplist = new List<string>();
List<string> allcplist = new List<string>();
foreach (ComponentPresentation cp in subject.ComponentPresentations)
{
allcplist.Add(cp.Component.Id + "," + cp.ComponentTemplate.Id);
}
List<string> uniquecplist = allcplist.Distinct().ToList();
if (allcplist.Count != uniquecplist.Count)
{
subject.Save(false);
throw new Exception("Page has duplicate component presentation");
}
catch(Exception)
{
}
}
But i am not deleting the duplicate CP present on the page. Do i need to add,
for each()
inside
if (allcplist.Count != uniquecplist.Count)
{
}

ASP NET MVC Error In Function

This is my code. I got this sample from the Internet and I tried to modify it.
private void FillGridData()
{
//IQueryable<SVC> query = _customerService.GetQueryable();
_dataContext = new dbServiceModelDataContext();
var query = from m in _dataContext.SVCs
select m;
query = AddQuerySearchCriteria(query, _grid.SearchForm);
int totalRows = query.Count();
_grid.Pager.Init(totalRows);
if (totalRows == 0)
{
_grid.Data = new List<SVC>();
return;
}
query = AddQuerySorting(query, _grid.Sorter);
query = AddQueryPaging(query, _grid.Pager);
List<SVC> customers = query.ToList(); //***ERROR IN HERE***//
_grid.Data = customers;
}
The error says "Cannot order by type 'System.Object'.", what is the matter?
Do you have solution for me?
This is The AddQuerySorting Method THE PROBLEM IS IN HERE
is there anything wrong about the code? :(
private IQueryable<SVC> AddQuerySorting(IQueryable<SVC> query, Sorter sorter)
{
if (String.IsNullOrEmpty(sorter.SortField))
return query;
//Used approach from http://www.singingeels.com/Articles/Self_Sorting_GridView_with_LINQ_Expression_Trees.aspx
//instead of a long switch statement
var param = Expression.Parameter(typeof(SVC), "customer");
var sortExpression = Expression.Lambda<Func<SVC, object>>
(Expression.Convert(Expression.Property(param, sorter.SortField), typeof(object)), param);
if (sorter.SortDirection == SortDirection.Asc)
query = query.OrderBy(sortExpression);
else
query = query.OrderByDescending(sortExpression);
return query;
}
here is AddQueryPaging Method
private IQueryable<SVC> AddQueryPaging(IQueryable<SVC> query, Pager pager)
{
if (pager.TotalPages == 0)
return query;
query = query.Skip((pager.CurrentPage - 1) * pager.PageSize)
.Take(pager.PageSize);
return query;
}
Sorter
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Web;
namespace MvcGridSample.ViewModels.Shared
{
public enum SortDirection
{
Asc = 1,
Desc = 2
}
public class Sorter
{
//Properties
public string SortField { get; set; }
public SortDirection SortDirection { get; set; }
public Sorter()
{
this.SortDirection = SortDirection.Asc;
}
public Sorter(string sortField, SortDirection sortDirection)
{
Verify.Argument.IsNotEmpty(sortField, "sortField");
Verify.Argument.IsNotEmpty(sortField, "sortDirection");
this.SortField = sortField;
this.SortDirection = sortDirection;
}
public void AddToQueryString(NameValueCollection queryString)
{
queryString["Sorter.SortField"] = this.SortField;
queryString["Sorter.SortDirection"] = this.SortDirection.ToString();
}
}
}
Look at the line:
var sortExpression = Expression.Lambda<Func<SVC, object>>
That should immediately leap out as the cause. The generated Expression must be suitable typed. This type of metaprogramming often involves either using the non-generic API, or using reflection to create the correct type on the fly. Fortunately, a suitable example is here. You should be able to use that approach re MakeGenericMethod (or simpler: just use the code "as is" from inside AddQuerySorting).

JavaScriptSerializer with custom Type

I have a function with a List return type. I'm using this in a JSON-enabled WebService like:
[WebMethod(EnableSession = true)]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public List<Product> GetProducts(string dummy) /* without a parameter, it will not go through */
{
return new x.GetProducts();
}
this returns:
{"d":[{"__type":"Product","Id":"2316","Name":"Big Something ","Price":"3000","Quantity":"5"}]}
I need to use this code in a simple aspx file too, so I created a JavaScriptSerializer:
JavaScriptSerializer js = new JavaScriptSerializer();
StringBuilder sb = new StringBuilder();
List<Product> products = base.GetProducts();
js.RegisterConverters(new JavaScriptConverter[] { new ProductConverter() });
js.Serialize(products, sb);
string _jsonShopbasket = sb.ToString();
but it returns without a type:
[{"Id":"2316","Name":"Big One ","Price":"3000","Quantity":"5"}]
Does anyone have any clue how to get the second Serialization work like the first?
Thanks!
When you create the JavaScriptSerializer, pass it an instance of SimpleTypeResolver.
new JavaScriptSerializer(new SimpleTypeResolver())
No need to create your own JavaScriptConverter.
Ok, I have the solution, I've manually added the __type to the collection in the JavaScriptConverter class.
public class ProductConverter : JavaScriptConverter
{ public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
Product p = obj as Product;
if (p == null)
{
throw new InvalidOperationException("object must be of the Product type");
}
IDictionary<string, object> json = new Dictionary<string, object>();
json.Add("__type", "Product");
json.Add("Id", p.Id);
json.Add("Name", p.Name);
json.Add("Price", p.Price);
return json;
}
}
Is there any "offical" way to do this?:)
Building on Joshua's answer, you need to implement a SimpleTypeResolver
Here is the "official" way that worked for me.
1) Create this class
using System;
using System.Web;
using System.Web.Compilation;
using System.Web.Script.Serialization;
namespace XYZ.Util
{
/// <summary>
/// as __type is missing ,we need to add this
/// </summary>
public class ManualResolver : SimpleTypeResolver
{
public ManualResolver() { }
public override Type ResolveType(string id)
{
return System.Web.Compilation.BuildManager.GetType(id, false);
}
}
}
2) Use it to serialize
var s = new System.Web.Script.Serialization.JavaScriptSerializer(new XYZ.Util.ManualResolver());
string resultJs = s.Serialize(result);
lblJs.Text = string.Format("<script>var resultObj = {0};</script>", resultJs);
3) Use it to deserialize
System.Web.Script.Serialization.JavaScriptSerializer(new XYZ.Util.ManualResolver());
var result = json.Deserialize<ShoppingCartItem[]>(jsonItemArray);
Full post here: http://www.agilechai.com/content/serialize-and-deserialize-to-json-from-asp-net/

Resources