Unable to display LINQ query output values from controller to view - c#

Controller
public ActionResult Track(string awb)
{
ViewBag.Title = "Track Your Shipment";
ViewBag.ErrorMessage = string.Empty;
ViewBag.ShipmentNo = awb;
FLCourierDetail trackOutput = new FLCourierDetail();
if (awb != null)
{
trackOutput = db.FL_CourierDetail.SingleOrDefault(fLCourierDetail => fLCourierDetail.AWBNumber == awb);
if (trackOutput != null)
{
var courierId = db.FL_CourierDetail.Where(s => s.AWBNumber == awb).Select(s => s.Courier);
var currentStatus = (from c in db.FL_CourierDetail
join s in db.FL_CourierStatus
on c.Courier equals s.CourierId
where c.AWBNumber == awb
select new { awb = c.AWBNumber, staus = s.StatusId, updated = s.StatusId, remark = s.Remark }).ToList();
ViewBag.CurrentStatus = currentStatus;
}
else
{
ViewBag.ErrorMessage = "Shipment number not found.";
}
}
else
{
ViewBag.ErrorMessage = "Please provide valid Shipment number.";
}
return View(trackOutput);
}
View
<div class="col-md-6">
#{
var status = ViewBag.CurrentStatus;
foreach (var item in status)
{
<p>#item</p>
}
}
</div>
If I iterate using foreach or if loop I am able to see the data in debug, but I am not able to write in html.
Debug
Web Page
Error
I am not able to read each value like awb, status, date etc.
Did I miss anything here?

The query result is an anonymous class, within the loop, each item is an object and thus the exception, object has now awb property.
One way to solve this is by defining a class:
public class Status {
public string awb { get; set; }
public int staus { get; set; }
public int updated { get; set; }
public string remark { get; set; }
}
Then your select would look like:
... select new Status { awb = c.AWBNumber, staus = s.StatusId, updated = s.StatusId, remark = s.Remark }).ToList();
Then, within the View:
var status = (List<Status>) ViewBag.CurrentStatus;
Another possible solution is to use strongly typed view model

Firstly, you could create a Model class for returned data;
var currentStatus = (from c in db.FL_CourierDetail
join s in db.FL_CourierStatus
on c.Courier equals s.CourierId
where c.AWBNumber == awb
select new CurrentStatus { awb = c.AWBNumber, staus = s.StatusId, updated = s.StatusId, remark = s.Remark }).ToList();
public class CurrentStatus
{
public string awb { get; set; }
public int staus { get; set; }
public int updated { get; set; }
public string remark { get; set; }
}
Secondly, you can't get output an entire object, you should specify properties which you want to display;
<div class="col-md-6">
#{
var status = (List<CurrentStatus>) ViewBag.CurrentStatus;
foreach (var item in status)
{
<p>#item.awb</p>
<p>#item.staus</p>
<p>#item.updated</p>
<p>#item.remark</p>
}
}
</div>

This is really strange, but in console application the following code actually works:
dynamic even = new List<int> { 1, 2, 3, 4 }
.Where(x => x % 2 == 0)
.Select((x, index) => new { Position = index, Num = x });
// Output:
// Position: 0, Number: 2
// Position: 1, Number: 4
foreach (dynamic item in even)
{
Console.WriteLine($"Position: {item.Position}, Number: {item.Num}");
}
However, in ASP.NET ths doesn't work, and I don't really understand because ViewBag is dynamic, too.
UPDATE
Same question was asked here. A quote from there:
You're returning an instance of an anonymous type. If you weren't using dynamic, your only choice here would be to return an object - the anonymous type is unknown outside of your own function. If you had a variable of type object, you'd get a compile time error that it doesn't have a LogoName property. All you've done with dynamic is defer exactly the same lookup rules until runtime. At runtime, the best type that can be determined is object.
As this answer states, the following must not work, but it works:
static void DoWork()
{
dynamic evens = GetEvens();
foreach (dynamic item in evens)
Console.WriteLine($"Position: {item.Position}, Number: {item.Num}");
}
static dynamic GetEvens() =>
new List<int> { 1, 2, 3, 4 }
.Where(x => x % 2 == 0)
.Select((x, index) => new { Position = index, Num = x });
In this case I return dynamic. However, the code work correctly.

Related

How can i create an object from this single string i've split?

im trying to make a report about supplies used by connecting to the technical service database and filtering supply audits, inside audits what i care about is ActionNotes which is a single long string formatted like this:
New Supplie Mobile added: /n Id: 1/n Name: Bateria /n Stock. 0/n Minimum Stock: 10/n IdSquad: 1/n IdSupplie: 1/n
I've managed to write this code which creates an array of strings after splitting and filtering the values that i don't need and comes out something like this:
private void ImportarServicioTecnico()
{
var auditList = db3.Audit.ToList();
var suppliesList = (from t in auditList where t.ActionNotes.ToLower().Contains("new supplie mobile added") select t).ToList();
foreach (var i in suppliesList)
{
InsumosST o = new InsumosST();
var note = i.ActionNotes;
Debug.WriteLine("Audit ID: " + i.Id.ToString() + " Date: " + i.AuditDate);
string[] lines = Regex.Split(note, "/n");
foreach (var l in lines)
{
var checkstring = l.ToLower();
string actual = l;
if (checkstring.Contains("new supplie mobile added") || checkstring.Contains("description:")) {continue;}
if (checkstring.Contains("stock."))
{
int pos2 = actual.IndexOf(".");
Debug.WriteLine(actual.Substring(pos2 + 1));
continue;
}
int pos = actual.IndexOf(":");
Debug.WriteLine(actual.Substring(pos + 1));
}
}
}
Audit ID: 21 Date: 15-11-2021 10:43:59
1 Bateria 0 1 0 1 1
The question being is: is it possible to create an object from my db model with this code?
This is my model:
public partial class InsumosST
{
public int id { get; set; }
public string supply { get; set; }
public Nullable<System.DateTime> entrydate { get; set; }
public string squad { get; set; }
}
enter code here
Sure.. Let's have some dictionary of delegates that assign values to the properties of InsumosST, split the line on /n then again on : to get an id and value, look for the id in the dictionary and if it;s there, call the delegate passing the value
private void ImportarServicioTecnico()
{
var auditList = db3.Audit.ToList();
var suppliesList = (from t in auditList where t.ActionNotes.ToLower().Contains("new supplie mobile added") select t).ToList();
//make a dictionary of the string we look for and the "method" to execute if we find that string
//the methods are one-liners that set the appropriate value on the object
var d = new Dictionary<string, Action<string, InsumosST>();
d["id"] = (v, i) => i.id = int.TryParse(v, out int z) ? z : SOME_DEFAULT_ID_HERE;
d["idsupplie"] = (v, i) => i.supply = v;
d["idsquad"] = (v, i) => i.squad = v;
foreach (var i in suppliesList)
{
var o = new InsumosST();
var bits = i.ActionNotes.Split("/n");
foreach (var line in lines)
{
var bits = line.Split(new[]{':','.'}, 2); //line is e.g. "idsupplie: 1"
if(bits.Length < 2) continue; //if we don't have an id and value
var id = bits[0].ToLower(); //e.g. "idsupplie"
var val = bits[1].Trim(); //e.g. "1"
if(d.TryGetValue(id, out var m)) //if we know this id, e.g. "id", "idsupplie", "idsquad"
m(val, o); //call the delegate; it will assign val to the right property of o
}
context.InsumosSts.Add(o);
}
context.SaveChanges();
}
I suppose the hardest thing to "get" about this is if you're not really used to delegates; you've used them (conceptually where t.ActionNotes.ToLower().Contains("new supplie mobile added") is such a thing => it's a method that produces a bool from some input value determined by from) but it doesn't mean you'd be familiar with them.
Simply put, delegates are a way of storing method code in a variable just like we store data. You can assign a method to a variable, and then execute the variable to run the code:
var someMethod = () => Debug.WriteLine("hello");
someMethod(); //prints hello
You can make them take parameters:
var someMethod = (string s) => Debug.WriteLine(s);
someMethod("hello"); //prints hello
So all we did here was make up a bunch of methods that assign props to a passed-in InsumosSt
var x = (InsumosST i, string v) => i.idsupplie = v;
x(someInsumosObject, "hello"); //assigns "hello" to someInsumosObject.idsupplie property
It means to support more properties, you just add them to the InsumosST and
write a dictionary entry that assigns them:
public partial class InsumosST
{
public int id { get; set; }
public string supply { get; set; }
public Nullable<System.DateTime> entrydate { get; set; }
public string squad { get; set; }
//new!
public string Name {get;set;}
}
d["name"] = (v, i) => i.Name = v;

Filter Data based on same ID

I have a model class
public class Model
{
public string name { get; set; }
public string files { get; set; }
}
I have a controller class that populates the data from database into this model
List<Model> model = new List<Model>();
while (reader.Read()){
var om = new Model();
if (reader != null)
{
om.name = reader.GetString(0);
om.files = reader.GetString(1);
model.Add(om)
}
How can I filter and combine all files that have the similar first names?
I read about linq and tried this
var jm = om.name
.Where(o => om.name.Contains(o))
.Select() ;
This might work for you:
var grouped = model.GroupBy(m => m.name).ToArray();
This will create an object grouped of type IGrouping<string, Model>[] (array of IGrouping...)
.ToArray() is optional and if you remove it, you get IEnumerable<IGrouping<string, Model>>, but don't let the nested <> scare you.
The items in your original list are grouped by name, so the group will have Key property that will be the same for each element in the group.
To print the results, for example:
foreach(var group in grouped)
{
Console.WriteLine($"Printing group: {group.Key}");
foreach(var model in group)
{
Console.WriteLine($"\tName: {model.name}, File: {model.file}");
}
}
Note that each element in a group is a collection of your model objects.
Use debugger to see what that structure looks like and if you need more help - ask...
Change your Model
public class Model
{
public string name { get; set; }
public IList<string> files { get; set; }
}
Use a Dictionary.
var models = new Dictionary<string, Model>();
while (reader.Read())
{
var om = new Model();
if (reader != null)
{
var name = reader.GetString(0);
var file = reader.GetString(1);
if (models.Contains(name))
models[name].files.Add(file);
else
{
models.Add(name, new Model
{
name = name,
files = new List<string>{files}
});
}
}
}
Then you can pull out a combined list with LINQ:
var peopleFileLists = models.Select(x => x.Value).ToList();
foreach(var person in peopleFileLists)
{
foreach(var file in person.files)
Console.WriteLine(person.name + "-" + file);
}

Group By query in mvc5

Hi i want to write sql Group by query in C# of my MVC5 application.
In the above image I have group by query which i wrote in sql . That I want to write in C# front end.
I tried to write query in front end. But I am getting error which is mentioned in the image. Now I want to write that Group By query in C# and want to display the each employee with count (output same as mentioned in the first image). Can anyone help me to resolve this issue?
My ViewModel(Dashnboard View model)
public class DashboardViewmodel
{
public List<CustomerTypeCountModel> CustomerTypesCountModels { get; set; }
public List<View_VisitorsForm> Visits { get; set; }
public CustomerTypeViewModel CustomerTypeViewModels { get; set; }
public int sizingcount { get; set; }
public int Processingcount { get; set; }
//here i declared two properties
public string EmployeeName { get; set; }
public string EmployeeCount { get; set; }
}
My Controller code
[HttpGet]
public ActionResult SalesVisit()
{
return View();
}
public ActionResult GetDatesFromSalesVisit(DashboardViewmodel dvm)
{
var fromdate = Convert.ToDateTime(dvm.CustomerTypeViewModels.FromDate);
var todate = Convert.ToDateTime(dvm.CustomerTypeViewModels.ToDate);
List<View_VisitorsForm> empcount = new List<View_VisitorsForm>();
if (DepartmentID == new Guid("47D2C992-1CB6-44AA-91CA-6AA3C338447E") &&
(UserTypeID == new Guid("106D02CC-7DC2-42BF-AC6F-D683ADDC1824") ||
(UserTypeID == new Guid("B3728982-0016-4562-BF73-E9B8B99BD501"))))
{
var empcountresult = db.View_VisitorsForm.GroupBy(G => G.Employee)
.Select(e => new
{
employee = e.Key,
count = e.Count()
}).ToList();
empcount = empcountresult ;//this line i am getting error
}
DashboardViewmodel obj = new DashboardViewmodel();
return View("SalesVisit", obj);
}
When you use a GroupBy you get an IEnumerable<IGrouping<Key,YourOriginalType>> so you do not have .Employee and .VisitingID properties.
Change as following:
public class EmployeeCount
{
public string Employee {get; set;}
public int Count {get; set;}
}
List<EmployeeCount> result = db.View_VisitorsForm
.Where(item => item.VisitingDate >= beginDate && item.VisitingDate < endDate)
.GroupBy(G => G.Employee)
.Select(e =>new EmployeeCount
{
employee = e.Key,
count = e.Count()
}).ToList();
//Now add the result to the object you are passing to the View
Also keep in mind that you are not instantiating objects of type View_VisitorsForm but an anonymous object so assigning the result to empcount yet alone with the added FirstOrDefault will not compile
To pass this structure to the View and present it check this question
hope this helps you
var query = db.View_VisitorsForm.Where(o => o.VisitingDate >= new DateTime(2016,10,01) && o.VisitingDate <= new DateTime(2016, 10, 30)).GroupBy(G => G.Employee)
foreach (var item in query)
{
Console.WriteLine($"Employee Id {item.Key} : Count :{item.Count()}");
}

Adding then Referencing multiple values within IEnumerable

I'm new to MVC. I have the following code in my method:
// Get list of news formats that were ticked
IEnumerable<int> newsFormatIds = viewModel.ClubNewsFormats
.Where(c => c.selected == true).
Select(c => c.NewsFormatId);
// Copy news formats
IEnumerable<ClubNewsFormat> clubNewsFormats = club.ClubNewsFormats.ToList();
// Remove previous formats
foreach (ClubNewsFormat previousClubNewsFormats in clubNewsFormats)
{
db.ClubNewsFormats.Remove(previousClubNewsFormats);
}
// Add new club news formats
foreach (int NewsFormatId in newsFormatIds)
{
NewsFormat newsFormat = db.NewsFormats.Find(NewsFormatId);
var newClubNewsFormat = new ClubNewsFormat {
ClubId = club.ClubId,
NewsFormatId = newsFormat.NewsFormatId,
Discount =
};
db.ClubNewsFormats.Add(newClubNewsFormat);
}
It gets a list of the items that were ticked in a view and then adds a record for each to the ClubNewsFormats table. By using the IEnumerable to generate a list of all the Model.ClubNewsFormats[c].NewsFormatId where Model.ClubNewsFormats[c].selected is true. As well as being able to select the the Id's you can also add a Discount for each Id. I want to be able to commit this Discount value for each Selected Id when saving them to the ClubNewsFormats Table.
How to I add the Discount to the IEnumerable as well as the Id so that I can commit it in the foreach (int NewsFormatId in newsFormatIds) loop?
The section of the view is:
#for (int c = 0; c < Model.ClubNewsFormats.Count(); c++)
{
<div>
#Html.HiddenFor(x => Model.ClubNewsFormats[c].NewsFormatId)
#Html.CheckBoxFor(x => Model.ClubNewsFormats[c].selected)
#Html.LabelFor(x => Model.ClubNewsFormats[c].Format, Model.ClubNewsFormats[c].Format)
#Html.EditorFor(x => Model.ClubNewsFormats[c].Discount)
</div>
}
The view model is:
public class ClubNewsFormatsViewModel
{
public int NewsFormatId { get; set; }
public string Format { get; set; }
public bool selected { get; set; }
[Display(Name = "Discount")]
public decimal Discount { get; set; }
}
which is referenced in the main view model by:
public ClubNewsFormatsViewModel[] ClubNewsFormats { get; set; }
I amended to controller to this:
// Remove previous formats
foreach (ClubNewsFormat previousClubNewsFormats in clubNewsFormats)
{
db.ClubNewsFormats.Remove(previousClubNewsFormats);
}
// Add new club news formats
foreach (ClubNewsFormatsViewModel clubNewsFormat in viewModel.ClubNewsFormats.Where(c => c.selected == true))
{
var newClubNewsFormat = new ClubNewsFormat { ClubId = club.ClubId, NewsFormatId = clubNewsFormat.NewsFormatId, Discount = clubNewsFormat.Discount };
db.ClubNewsFormats.Add(newClubNewsFormat);
}

Get all business units

I am trying to retrieve all business units from CRM 2013.
Tried the following query
var query = _serviceContext.BusinessUnitSet
.Where(b => b.EntityState == 0)
.Select(x => new
{
Name = x.Name,
Id = x.Id
}
)
.ToList();
Using this query I am receiving an error just stating:
{System.ServiceModel.FaultCode} {attributeName} {System.Collections.Generic.SynchronizedReadOnlyCollection<System.ServiceModel.FaultReasonText>}
When googling on the subject I found information about how to retrieve single business units (which seems to be different from retrieving a "normal" entity), but not how to get them all (link).
Any help as to how I would retrieve all business units would be much appreciated.
Try this using QueryExpression
public class BusinessUnit
{
public Guid Id { get; set; }
public String Name { get; set; }
}
public void GetAllBusinessUnits(Action<QueryExpression> queryModifier = null)
{
foreach (BusinessUnit m in RetrieveAllBusinessUnit(this.Service, 1000, queryModifier))
{
//Console.WriteLine(m.Name);
}
}
public static IEnumerable<BusinessUnit> RetrieveAllBusinessUnit(IOrganizationService service, int count = 1000, Action<QueryExpression> queryModifier = null)
{
QueryExpression query = new QueryExpression("businessunit")
{
ColumnSet = new ColumnSet("businessunitid", "name"),
PageInfo = new PagingInfo()
{
Count = count,
PageNumber = 1,
PagingCookie = null,
}
};
if (queryModifier != null)
{
queryModifier(query);
}
while (true)
{
EntityCollection results = service.RetrieveMultiple(query);
foreach (Entity e in results.Entities)
{
yield return new BusinessUnit()
{
Id = e.GetAttributeValue<Guid>("businessunitid"),
Name = e.GetAttributeValue<String>("name")
};
}
if (results.MoreRecords)
{
query.PageInfo.PageNumber++;
query.PageInfo.PagingCookie = results.PagingCookie;
}
else
{
yield break;
}
}
}
I presume you want to get all active business units from system. So you must use IsDisabled property to get them. The property you use EntityState is used for tracking the entity state in context, not to indicate state of entity in CRM. See BusinessUnit Entity for more info about BU entity.

Categories

Resources