IQueryable changed in foreach loop not displaying in view - asp.net-mvc

I been trying to change the value of RouteAttr.RoutedForRole if it is equal to
SHead but I checked in run time and the query was not changed even though it went to the foreach loop and there were valid entries. I also tried adding the foreach loop in the view but it didn't change anything.
public ViewResult Index()
{
IQueryable<ServiceRequestViewModel> query;
query = from c in context.ServiceRequests
select new ServiceRequestViewModel
{
ServiceRequestId = c.ServiceRequestId,
ServiceDescription = c.ServiceDescription,
RequestNumber = c.RequestNumber,
Title = c.Title,
RouteAttr = c.RouteAttr,
LogAttr = c.LogAttr
};
foreach (var item in query)
{
if (item.RouteAttr.RoutedForRole == WorkflowRole.SHead)
{
item.RouteAttr.RoutedForRole = WorkflowRole.HRManager;
}
}
return View(query);
}
Below is my gridview.
#Html.Grid(Model).Columns(col =>
{
col.Add(o => o.ServiceRequestId)
.Encoded(false)
.Sanitized(false)
.Filterable(true)
.Titled("SRF No.")
.SetWidth(150)
.RenderValueAs(o => Html.ActionLink(o.RequestNumber, "Details", new { id = o.ServiceRequestId }));
col.Add(o => o.Title)
.Filterable(true)
.SetWidth(400)
.Titled("Title");
col.Add(o => o.LogAttr.CreatedBy)
.Filterable(true)
.Titled("Requestor");
col.Add(o => o.RouteAttr.RoutedForRole)
.Filterable(true)
.Titled("Status");
}).WithPaging(10).Sortable(true)
I've been told in the comments why it's not returning so now I want to know how to update an item in iqueryable and return it in view.

Just like what #Enigmativity said in the comments, I changed the query into an array.
var data = query.ToArray();
He suggested I return data but it didn't work since ServiceRequestViewModel requires an IQueryable type. So I changed it back to IQueryable type so I can return it to view.
var queryable = data.AsQueryable();

Related

Orderby clause not working with drop down list in mvc

I am populating a drop down list using Linq and the orderby clause doesn't seem to work.
public List<Hello> getManagers()
{
var que = (from man in db.Table1
where man.Role == "Manager"
orderby man.Name
select new Hello
{
Managers = man.Name
}).Distinct().ToList();
return que;
}
Controller Class:
public ActionResult Index()
{
rp = new RequestProcess();
ViewBag.ID = fillSelectedList("", "ID", rp);
ViewBag.Managers = fillSelectedList("", "Managers", rp);
return View(""); //View 1
}
public static List<SelectListItem> fillSelectedList(string selValue, string type, RequestProcess rp )
{
List<SelectListItem> list = new List<SelectListItem>();
SelectListItem obj = new SelectListItem();
if (type == "Managers") {
var tempList= rp.getManagers();
tempList.ForEach(x =>
{
obj = new SelectListItem();
obj.Text = x.Managers;
obj.Value = x.Managers;
obj.Selected = x.Managers == selValue ? true : false;
list.Add(obj);
});
}
return list;
}
I am still receiving an un-ordered list. Any fixes?
The result is not ordered, because method Distinct does not return ordered results. What you need to do instead is to first call Disctinct, and only then OrderBy:
var que = (from man in db.Table1
where man.Role == "Manager"
select new Hello
{
Managers = man.Name
}).Distinct() // <- First distinct ...
.OrderBy(x => x.Managers) // <- ... then order by
.ToList();
As mentioned in the answer above, you need to sort the result after Distinct().
Also note that you are mixing Lambda expression and LINQ to Entities Queries... you may want to consider choosing one of them for consistency (though there is no syntax error if you mix them). This is the same query using lambda expression:
var que = _context.Table1
.Where(m => m.Role == "Manager")
.Select(h => new Hello { Managers = h.Name })
.Distinct()
.OrderBy(o => o.Managers)
.ToList();

Retrieve all drop-down values from database and show the saved value as selected one in drop down

I am using a kendo grid with pop up editing mode and editor template in mvc4. The template consists of a drop down list which is bound through database. The problem comes when in Edit operation all other data is retrieved along with all elements of drop down list and displayed in respective html attributes such a textbox ,checkbox etc but the value which i have saved from drop down list is not shown auto selected there.
Example
During add operation i have selected "Work" from the drop down list and saved it in database. At the time of Edit i want "Work" to be shown auto selected in drop down list.
[AcceptVerbs(HttpVerbs.Post)]
public JsonResult Update([DataSourceRequest] DataSourceRequest request,Model object)
{
if (obj == null || !ModelState.IsValid) return null;
var obj = _Repo.FindBy(t => t.ID == object.ID);
obj.Text = object.Text;
obj.Type = object.Type;
obj.MasterTypeID_Fk = new Guid(object.Type);
obj.Notes = object.Notes;
obj.Primary = object.Primary;
obj.LastVerified = DateTime.Now.ToUniversalTime();
obj.LastUpdated = DateTime.Now.ToUniversalTime();
_Repo.Update(obj);
var result = new[] { object }.ToDataSourceResult(request, ModelState);
return Json(result);
}
//this is my code for ddl in editor template
#(Html.Kendo().DropDownList()
.Name("Type")
.DataTextField("Value")
.DataValueField("TypeID")
.DataSource(source =>
{
source.Read(read => { read.Action("GetTypes", "Dashboard"); });
})
)
// this is code in controller to bind ddl
public ActionResult GetTypes()
{
List<TypeModel> Type = _Repo.GetTypes().ToList().ToMap<TypeBO, TypeModel>();
Type.Insert(0, new TypeModel() { Value = "--Select--", TypeID = Guid.Empty });
return Json(Type, JsonRequestBehavior.AllowGet);
}
You can set your value in Html helper using Value("ValueData"):
#(Html.Kendo().DropDownList()
.Name("Type")
.DataTextField("Value")
.DataValueField("TypeID")
.DataSource(source =>
{
source.Read(read => { read.Action("GetTypes", "Dashboard"); });
})
.Value("ValueData")
)
Like in this example: http://demos.telerik.com/aspnet-mvc/dropdownlist/index

Kendo UI treeview binding

I want to make a Kendo TreeView that shows all nodes on first load. I'm using the Kendo 'Binding to remote data' sample but it doesn't work correctly. It shows just the first level and the id passed to the controller action is always null.
Please help me.
View code :
#(Html.Kendo().TreeView()
.Name("treeview")
.DataTextField("Title")
.ExpandAll(true)
.LoadOnDemand(false)
.DataSource(dataSource => dataSource
.Read(read => read.Action("Employees", "Follow").Data("addData"))))
function addData(data) {
return { id: data.id };
}
Controller code : (controller Follow)
public System.Web.Mvc.JsonResult Employees(int? id)
{
System.Collections.Generic.List<FollowType> List =
new System.Collections.Generic.List<FollowType>();
if (id.HasValue == true) {
List = FollowTypeList.FindAll(current => current.ParentId == id);
} else {
List = FollowTypeList.FindAll(current => current.ParentId == null);
}
System.Collections.Generic.List<Kendo.Mvc.UI.TreeViewItemModel> NodeList =
new System.Collections.Generic.List<Kendo.Mvc.UI.TreeViewItemModel>();
foreach (CommonData.Domain.FollowType item in List)
{
NodeList.Add(new Kendo.Mvc.UI.TreeViewItemModel() {
Id = item.Id.ToString(),
Text = item.Title,
HasChildren = FollowTypeList.Exists(c => c.Id == item.ParentId)
});
}
return Json(NodeList, System.Web.Mvc.JsonRequestBehavior.AllowGet);
}
I guess that in your javascript code, the id field of data should be Id (be careful to the capitalization) :
return { id : data.Id };

MVC with Kendo treeview - remote data JSON or XML

I'm trying to create a Kendo treeview that gets populated from my controller (PropertyController).
The part I'm stuck at is how to format my data in the controller. How could I create a treeview three items deep and pass that to my view to be displayed in the treeview?
#(Html.Kendo().TreeView()
.Name("treeview")
.Events(events => events
.DragStart("PartnershipPage.OnDragStart")
.Drop("PartnershipPage.OnDrop")
.DragEnd("PartnershipPage.OnDragEnd")
)
.HighlightPath(true)
.DragAndDrop(true)
.DataSource(dataSource => dataSource
.Read(read => read
.Action("Index","Tree")
)
)
)
I've included the controller to see if I'm doing it correctly. All that is happening so far is the JSON is being displayed on the screen as text.
Controller:
public ActionResult Index()
{
var org = new Entities();
var eList = new List<Entity>();
var entity1 = new Entity
{
Id = 1,
Name = "LLC-A",
parentId = 0
};
eList.Add(entity1);
var entity2 = new Entity
{
Id = 2,
Name = "LLC-B",
parentId = 0
};
eList.Add(entity2);
var entity3 = new Entity
{
Id = 1,
Name = "LLC-C",
parentId = 2
};
eList.Add(entity3);
var entity4 = new Entity
{
Id = 1,
Name = "LLC-D",
parentId = 2
};
eList.Add(entity4);
org.Entity = eList;
var test = from x in org.Entity
where (x.Name != null)
select new
{
Id = x.Id,
Name = x.Name,
parentId = x.parentId
};
;
return Json(test, JsonRequestBehavior.AllowGet);
}
From: Kendo Site
<%= Html.Kendo().TreeView()
.Name("TreeView")
.BindTo(Model, mapping => mapping
.For<Customer>(binding => binding
.Children(c => c.Orders) // The "child" items will be bound to the the "Orders" property
.ItemDataBound((item, c) => item.Text = c.ContactName) // Map "Customer" properties to TreeViewItem properties
)
.For<Order<(binding => binding
.Children(o => null) // "Orders" do not have child objects so return "null"
.ItemDataBound((item, o) => item.Text = o.OrderID.ToString()) // Map "Order" properties to TreeViewItem properties
)
)
%>
You could put your entities into a list called for example, "myEntities" and return that from the controller to the view:
public ActionResult Index()
{
var ents = getMyEntities(); // some method you have to return the list of your entities
return ents;
}
Then in your view, you can loop through all the Entities in your Model:
#(Html.Kendo().TreeView()
.Name("TreeView")
.Items(treeview =>
{
foreach (var entity in Model)
{
var entityName = entity.Name;
var children = entity.Children;
treeview.Add().Text(entityName ).Expanded(false).Items(branch =>
{
if (children != null)
{
foreach (var child in children)
{
branch.Add().Text(child);
}
}
});
}
}
)
)
I used children because I found it easier to use than parent and so I would change my Entities to something like this:
var entity4 = new Entity
{
Id = 1,
Name = "LLC-D",
Children = <list of children names ... >
};
You can see how I did mine here: Populate KendoUI Treeview with RavenDB Documents
Hope this helps.
Edit in response to: How can I display children of children?
I ran into the same problem as you describe (displaying children of children). Here is how I did it after I had the problem of displaying children of children:
I used EntityFramework:
The DB context class:
public class EntityDBContext : DbContext
{
public DbSet<MyEntity> Entities { get; set; }
}
Controller:
public JsonResult EntitiesForTreeView(int? id)
{
// Here I am using EntityFramework
var entitiesContext = new EntityDBContext();
var myEntity= from e in entitiesContext.Entities
where (id.HasValue ? e.Parent == id : e.Parent == null)
select new
{
id = e.Id,
Name = e.Name,
hasChildren = e.Id
};
return Json(myEntity, JsonRequestBehavior.AllowGet);
}
And the View:
#(Html.Kendo().TreeView()
.Name("treeview")
.DataTextField("Name")
.LoadOnDemand(true)
.HighlightPath(true)
.DataSource(dataSource => dataSource
.Read(read => read
.Action("EntitiesForTreeView", "SiteMap")
)
)
.Checkboxes(true)
)
Hope this helps. Sorry if there is something stupid - I've only been doing web development for 3 months so unmark as answer if needed. Let me know if I can help further. PS: I should mention that after implementing the solution I have shown above, I noticed that the nodes on my tree all have the "+" sign... regardless of whether or not they have any children. If you know how to fix this, please let me know :)

Problem with using a ToExpando method

Hi I i try to use a ToExpando solution to use anonymous classes in razor views.
I use this solution -> Dynamic Anonymous type in Razor causes RuntimeBinderException
I'll write what i did:
I added a file Extensions.cs where i put following code:
public static class Extensions
{
public static ExpandoObject ToExpando(this object anonymousObject)
{
IDictionary<string, object> anonymousDictionary = HtmlHelper.AnonymousObjectToHtmlAttributes(anonymousObject);
IDictionary<string, object> expando = new ExpandoObject();
foreach (var item in anonymousDictionary)
expando.Add(item);
return (ExpandoObject)expando;
}
}
I wrote a query that receive a tuples from database in controller method:
IEnumerable<dynamic> articles = (from p in db.Articles.Where(p => p.user_id == 2)
select new
{
p.article_id,
p.title,
p.date,
p.category,
AverageScore = db.Articles_Scores
.Where(o => o.user_id == p.user_id && p.article_id == o.article_id)
.Average(m => m.score)
}).AsEnumerable()
.Select(r => r.ToExpando());
int ii = 0;
foreach(var it in articles) {
// HERE I CAN READ EVERYTHING
ii = it.article_id;
}
return View(articles);
In view I declare a model:
#model IEnumerable<dynamic>
And I try to get every tuples:
#foreach (dynamic item in Model) {
// some code
#item.article_id // HERE IS EXCEPTION
}
In the foreach line I got an Exception:
RuntimeBinderException: 'System.Dynamic.ExpandoObject' does not contain a definition for 'article_id'
What did I do wrong?
You need to call .AsEnumerable() or .ToList() first to force ToExpando to run on the client.
Try:
dynamic articles = (from p in db.Articles.Where(p => p.user_id == 2_
select new
{
p.article_id,
p.title,
p.date,
p.category,
AverageScore = db.Articles_Scores
.Where(o => o.user_id == p.user_id && p.article_id == o.article_id)
.Average(m => m.score)
}).AsEnumerable()
.Select(r => r.ToExpando());
Edit: Make sure you declare dynamic not var
Edit 2: In your for look, you're declaring var again. Change it to:
#foreach (dynamic item in Model) {
// some code
#item.article_id // HERE IS EXCEPTION
}
Ok, building on the first two answers, I added another extension method that I'm surprised I don't see here:
public static List<ExpandoObject> ToExpandoList<T>(this IEnumerable<T> ie) {
return ie.Select(o => o.ToExpando()).ToList();
}
And now in my view I have code like this, and it works just fine using Razor.
var peoples = from f in "tom dick susan roberto".Split(' ')
select new { FirstName = f, Age = f.Length };
ViewBag.People = peoples.ToExpandoList();
The problem is HtmlHelper.AnonymousObjectToHtmlAttributes(), it's replacing
'_' with '-' for the property name. Look at the comment for the method.

Resources