How to return two models in MVC? - c#

I have this function that will be called in the controller:
public EditViewModel PostEditViewModel(EditViewModel model)
{
using (var db = new NorthwindEntities())
{
var prod = db.Products.Where(x => x.Id == model.Id).Single();
{
prod.Id = model.Id;
...
//I need something like this:
//prod.CategoryID = model.CategoryList.CatId
//but obviously intellisense tells me that after the dot of CategoryList, only methods of that list can be called.
db.SaveChanges();
}
and this is my ViewModel:
public int Id{ get; set; }
...
public IEnumerable<Categories> CategoryList { get; set; }
public class Categories {
public int ProdId { get; set; }
public int? CatId { get; set; }
public string CatName { get; set; }
}
how do I call the CategoryList through my EditViewModel so that I can edit the Category of a specific product through HTML.DropdownList?

If your product model have CategoryId property (I just can't see it in your question) and you using strongly typed View You always can use this overload of DropDownListBoxFor() helper:
#Html.DropDownListFor(
x => x.CategoryId,
new SelectList(Model.CategoryList, "CatId", "CatName")
)
But actually i recomend you to use SelectListItem in ViewModels for all your dropdowns, becouse it's really bad practice - put domain entity on your View
Than your ViewModel will be like:
public int Id { get; set; }
public int CategoryId { get; set; }
...
public IEnumerable<SelectListItem> CategoryList { get; set; }
And on the View you can do this way:
#Html.DropDownListFor(x => x.CategoryId, Model.CategoryList)
In your GET ViewModel Controller you can initialize your CategoryList like this:
model.CategoryList = db.Categories.OrderBy(x => x.Name)
.Select(x => new SelectListItem
{
Text = x.Name,
Value = x.Id.ToString()
});
It really helps you to get your Views cleaner.

It looks like CategoryList is used to populate the items in your DropDownList, and CatId is the property on your view model that captures the ID value of the selected category.
If that is the case, you can just assign it like so:
if (model.CatId.HasValue)
{
prod.CategoryID = model.CatId.Value;
}

If I not mistaken and I understood you, you should to create class EditViewModel in this class create the fields:
public int Id{ get; set; }
...
public IEnumerable<Categories> CategoryList { get; set; }
Next, in your controller, you should use the following code:
var prod = db.Products.Where(x => x.Id == model.Id).Single();
{
prod.Id = model.Id;
...
prod.CategoryID = model.CategoryList.Select(m => m.CatId)
//but Select returned the List of CatId, I suggest thet prod.CategoryID is List
}
db.SaveChanges();

Related

How can i fill a value from one my domain model to my edit model?

In my project i have : countries and CountryEditModel.
public class countries
{
public int id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
}
public class CountryEditModel
{
public int id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public bool isvalid{ get;set; }
}
countries is my domain model which is binded with entity framework and countryEditModel is the model which i use in my views.
How can i fill values from countries to countryEditModel. I actually want to bind list of all countries to dropdownlist in my view and I don't want to use my countries domain model directly in my view.
To solve i have done this
var countryDomain = context.Country.Select(c => c).ToList();
var countrylist = new List<CountryEditModel>();
var countrymodel = new CountryEditModel();
foreach (var country in countryDomain)
countrymodel = new CountryEditModel()
{
Code = country.Code,
Name = country.Name,
id = country.id
};
countrylist.Add(countrymodel);
Is there any better way?
Answer:
Actually this is what i exactly wanted to do
var countryViewModel = context.Country.Select(c => new CountryEditModel
{
Code = c.Code,
Name = c.Name,
id = c.id
}).ToList();
As indicated by the #rohitsingh this is what he exactly wanted to do
var countryViewModel = context.Country.Select(c => new CountryEditModel
{
Code = c.Code,
Name = c.Name,
id = c.id
}).ToList();

how to use ICollection for SelectList in Contoller of MVC?

I am developing .NET MVC application.
I want to send the collection of the objects from controller to View using select list.
without using view bag.
ViewModel :
public class AdviceCreateVM
{
public int Id { get; set; }
public string AdviceNo { get; set; }
public ICollection<CompanyVM> Companies { get; set; }
}
public class CompanyVM
{
public int Id { get; set; }
public string Name { get; set; }
}
Controller Code :
public class AdviceCreateController : Controller
{
public ActionResult Create()
{
adviceVM.Companies = new SelectList(ledgerService.GetAll().OrderBy(t => t.Name), "Id", "Name");
}
}
It gives an error -
Cannot implicitly convert type 'System.Web.Mvc.SelectList' to
'System.Collections.Generic.ICollection'. An
explicit conversion exists (are you missing a cast?)
You're trying to assign a SelectList to property of type ICollection<CompanyVM> -- which won't work. You need some like:
var viewModel = new AdviceCreateVM
{
adviceVM.Companies =
ledgerService.GetAll().OrderBy(t => t.Name)
.Select(t=>
new CompanyVM
{
Id = t.Id, // "Id"
Name = t.Name // "Name"
})
.ToList()
};
I'm just guessing on the assignments here, since you didn't specify them.
In the view, you will have to make the select list from Companies property.
#Html.DropDownListFor(model => model.CompanyId,
model.Companies.Select(company =>
new SelectListItem
{
Value = company.Id,
Text = company.Name
}), "--Select Company--")
As indicated in the comments, SelectList does not implement ICollection. Change you view model collection to SelectList
public class AdviceCreateVM
{
public int Id { get; set; }
public string AdviceNo { get; set; }
public SelectList Companies { get; set; } // change to select list
public int CompanyID { get; set; } // for binding the the drop down list
}
Controller
public ActionResult Create()
{
AdviceCreateVM model = new AdviceCreateVM(); // initialise model
model.Companies = new SelectList(ledgerService.GetAll().OrderBy(t => t.Name), "Id", "Name");
}
View
#model YourAssembly.AdviceCreateVM
#using (Html.BeginForm()) {
....
#Html.DropDownFor(m => m.CompanyID, Model.Companies)
...

Returning multiple object properties in a list

I'm able to return the CategoryName field into a list via ViewBag.Categories. I also want to return the CategoryId field and use it to dynamically build the category Details view URL
This is the controller action:
public ActionResult Details(Item item)
{
var db = new appContext();
ViewBag.Item = item.ItemTitle;
ViewBag.ItemLink = "http://localhost:4444/Items/Details/" + item.ItemId;
ViewBag.Categories = new List<string>(item.Categories.Select(c => c.CategoryName));
return View();
}
This is the view where the list of categories is returned:
#foreach (string category in ViewBag.Categories)
{
<li>
#category
</li>
}
How can I return CategoryIdas shown above?
Use custom class for storing categories:
public class CategoryViewModel
{
public int CategoryId { get; set; }
public string CategoryName { get; set; }
}
Assign it like this:
ViewBag.Categories = item.Categories
.Select(c =>
new CategoryViewModel
{
CategoryId = c.CategoryId,
CategoryName = c.CategoryName
}).ToList();
And in your view use it like this:
#foreach (CategoryViewModel category in ViewBag.Categories)
{
<li>
#category.CategoryName
</li>
}
You can use anonymous types to achieve this:
public ActionResult Details(Item item)
{
var db = new appContext();
ViewBag.Item = item.ItemTitle;
ViewBag.ItemLink = "http://.../Items/Details/" + item.ItemId;
ViewBag.Categories = item.Categories.Select(c => new { c.CategoryName, c.CategoryId });
return View();
}
Then in your view:
#foreach (var category in ViewBag.Categories)
{
<li>
#category.CategoryName
</li>
}
However, you may want to consider replacing the ViewBag with strongly-typed models. It offers a lot of great benefits - including IntelliSense support.
Instead of using a List<string> you could use a:
List<Tuple<int, string>>
E.g.
ViewBag.Categories = item.Categories.Select(cat =>
Tuple.Create(cat.CategoryID, cat.CategoryName)).ToList();
Define a view-model like this:
public class CustomViewModel
{
public string Item { get; set; }
public string Title { get; set; }
public Categories Categories { get; set; }
}
public class Categories
{
public int Id { get; set; }
public string CategoryName { get; set; }
}
public ActionResult Details(Item item)
{
var db = new appContext();
var model = new CustomViewModel{
Item = item.ItemTitle,
ItemLink = "http://localhost:4444/Items/Details/" + item.ItemId,
Categories = (item.Categories.Select(c =>
new Categories{ Id = c.Id,CategoryName= c.CategoryName})).ToList()
};
return View(model);
}
and view like:
#model Categories
#foreach (Categories category in Model.Categories)
{
<li>
#category.CategoryName
</li>
}

Populate Result Set in SelectList MVC3

I have following SelectList declaration in CourseRegisterModel:
public class CourseRegisterModel
{
public StudentModel Student { get; set; }
public CourseModel Course { get; set; }
public IEnumerable<SelectListItem> CoursesList { get; set; }
public DateTime RegisterDate { get; set; }
}
In CourseController I am retrieving all available courses by calling wcf web service:
public ViewResult Index()
{
ServiceCourseClient client = new ServiceCourseClient();
Course[] courses;
courses = client.GetAllCourses();
List<CourseModel> modelList = new List<CourseModel>();
foreach (var serviceCourse in courses)
{
CourseModel model = new CourseModel();
model.CId = serviceCourse.CId;
model.Code = serviceCourse.Code;
model.Name = serviceCourse.Name;
model.Fee = serviceCourse.Fee;
model.Seats = serviceCourse.Seats;
modelList.Add(model);
}
return View(modelList);//RegisterCourses.chtml
}
I need to populate these courses in a dropdown on view RegisterCourses.chtml. How to put all records in selectlist in above code? Also how would i use that selectlist on view?
For starters, your RegisterCourses.cshtml needs to use:
#model <namespace>.CourseRegisterModel
Then, your controller code would be:
public ViewResult Index()
{
ServiceCourseClient client = new ServiceCourseClient();
Course[] courses;
courses = client.GetAllCourses();
CourseRegisterModel model = new CourseRegisterModel();
//model = other model population here
model.CourseList = courses.Select(sl => new SelectListItem()
{ Text = sl.Name,
Value = sl.CId })
.ToList();
return View(model);
}
And finally, back to your view (RegisterCourses.cshtml) - it should contain:
#Html.DropDownListFor(m => m.Course.CId, Model.CourseList)
Use the Html.DropDownList method: http://msdn.microsoft.com/en-us/library/dd492738(v=vs.108).aspx
Pass in the desired name of the drop down list as first argument, as second argument pass in your CourseList:
#Html.DropDownList("CoursesList", Model.CoursesList)

RavenDb Hierarchial Data Index

My data model is:
public class Category
{
public Guid Id { get; set; }
public List<Category> children { get; set; }
}
All I want is to get data from any level of nesting.
I've created an index for that:
public class CategoriesIndex :
AbstractIndexCreationTask<Category, CategoriesIndex.ReduceResult>
{
public class ReduceResult
{
public Guid Id { get; set; }
public Category Category { get; set; }
}
public CategoriesIndex()
{
Map = categories =>
from category in categories
from subcategory in category.Hierarchy(x=>x.children)
select new {
Id = subcategory.Id,
Category = subcategory
};
Store(x => x.Id, FieldStorage.Yes);
Store(x => x.Category, FieldStorage.Yes);
}
}
After running that code i've got an exception
Url: "/indexes/CategoriesIndex"
System.InvalidOperationException: Source code.
What's wrong? And if it is how can I index hierarchial data?
P.S. I can't change data model due to some restrictions
Update
I've got the message of the exception:
public class Index_CategoriesIndex : AbstractViewGenerator
{
public Index_CategoriesIndex()
{
this.ViewText = #"docs.Categories.SelectMany(category => category.Hierarchy(x => x.children), (category, subcategory) => new() {
Id = subcategory.Id,
Category = subcategory
})";
this.ForEntityNames.Add("Categories");
this.AddMapDefinition(docs => docs.Where(__document => __document["#metadata"]["Raven-Entity-Name"] == "Categories").SelectMany((Func<dynamic, IEnumerable<dynamic>>)(category => (IEnumerable<dynamic>)(category.Hierarchy(x => x.children))), (Func<dynamic, dynamic, dynamic>)((category, subcategory) => new { Id = subcategory.Id, Category = subcategory, __document_id = category.__document_id })));
this.AddField("Id");
this.AddField("Category");
this.AddField("__document_id");
}
} e:\RavenDB\Web\Tenants\RavenPortalAuth\IndexDefinitions\TemporaryIndexDefinitionsAsSource\4jy1udpm.0.cs(21,223) :
error CS1977: Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type
You should use AbstractIndexCreationTask's Recurse method.
http://ravendb.net/docs/2.0/client-api/querying/static-indexes/indexing-hierarchies

Categories