Hello I am creating a Store in ASP.NET MVC 5. I have gotten stuck here in the details ActionMethod. I have created the store to show Genres then Specific albums for that genre. Now i need to show the details of any single album that the user clicks on.
public class StoreController : Controller
{`
enter code here
private MVCMusicStoreDB db = new MVCMusicStoreDB();
// GET: Store
public ActionResult Browse()
{
return View(db.Genres.ToList());
}
public ActionResult Index(int id)
{
var albums = db.Albums.Where(a => a.GenreId==id);
return View(db.Albums.ToList ());
}
public ActionResult Details(int id)
{
var album = db.Albums;
return View();
}
}
}
I'm assuming that your Albums DbSet has a key named Id
On your Details action use this code to get one unique album
public ActionResult Details(int id)
{
var album = db.Albums.Where(a => a.Id == id).FirstOrDefault();
return View(album);
}
Should be something like this:
public ActionResult Index(int id)
{
var albums = db.Albums.Where(a => a.GenreId==id).ToList();
return View(albums); //Here u will return the albums with GenderId = Id
}
public ActionResult Details(int id)
{
var album = db.Albums.Where(a=>a.AlbumId == id).FirstOrDefault();
return View(album ); //Here u will return the albums with AlbumId = Id
}
Related
What I'm trying to do is create a site in Orchard that doesn't have a way for a user to register. An administrator will create the users.
What I have is module that defines the parts, records, views, etc. That is basically working.
Now what I'm trying to do is add a UserPart (from Orchard.Users) to one of the parts in my module.
I'm not sure how to do that. I need the fields displayed for the UserPart with the fields for the parent part in the same view. This also needs to be done in a way that when a save happens, all of the UserPart fields get sent to the Orchard.Users module.
Any suggestions, pointers or links on how to do that?
Thanks!
UPDATE...
The Activating Filter is an interesting idea. I initially chose the migration route. For now, I'll try and get that method working.
For simplicity, let's say I have a "Company" type (there's more to the actual type) that has a "CompanyName" and a UserPart.
Here's what the different pieces look like...
Migrations.cs (simplified)
public int Create()
{
SchemaBuilder.CreateTable("CompanyPartRecord", table => table.ContentPartRecord()
.Column("CompanyName", DbType.AnsiString, c => c.WithLength(50))
.Column("UserId", DbType.Int32));
SchemaBuilder.CreateForeignKey("FK_CompanyPartRecord_UserPartRecord", "CompanyPartRecord", new[] {"UserId" }, "Orchard.Users", "UserPartRecord", new[] { "Id" })
ContentDefinitionManager.AlterTypeDefinition("Company", type => type.WithPart("CommonPart").WithPart("UserPart"));
}
CompanyPartRecord
public class CompanyPartRecord : ContentPartRecord
{
public virtual string CompanyName { get; set; }
public virtual int? UserId { get; set; }
}
CompanyPart
public class CompanyPart : ContentPart<CompanyPartRecord>
{
internal LazyField<UserPart> UserPartField = new LazyField<UserPart>();
public string CompanyName
{
get { return Record.CompanyName; }
set { Record.CompanyName = value; }
}
public UserPart User
{
get { return UserPartField.Value;}
set { UserPartField.Value = value; }
}
}
Handler
public class CompanyPartHandler : ContentHandler
{
private readonly IContentManager _manager;
public CompanyPartHandler(IRepository<CompanyPartRecord> repository, IContentManager manager)
{
_manager = manager;
Filters.Add(StorageFilter.For(repository));
OnActivated<CompanyPart>(OnActivatedHandler);
}
private void OnActivatedHandler(ActivatedContentContext context, CompanyPart part)
{
if(part.User == null)
{
part.User = _manager.Create<UserPart>("User");
}
else
{
part.User = _manager.Get<UserPart>(part.User.Id);
}
}
}
Driver
public class CompanyPartDriver : ContentPartDriver<CompanyPart>
{
protected override DriverResult Editor(CompanyPart part, dynamic shapeHelper)
{
return ContentShape("Parts_Company_Edit", () => shapeHelper.EditorTemplate(TemplateName: "Parts/Company",
Model: part, Prefix: Prefix));
}
protected override DriverResult Editor(CompanyPart part, IUpdateModel updater, dynamic shapeHelper)
{
updater.TryUpdateModel(part, Prefix, null, null);
return Editor(part, shapeHelper);
}
}
Controller
public class AdminCompanyController : Controller, IUpdateModel
{
private readonly IOrchardServices _services;
private readonly INotifier _notifier;
private readonly IContentManager _contentManager;
private readonly ITransactionManager _transactionManager;
private readonly Localizer T = NullLocalizer.Instance;
public AdminCompanyController(IOrchardServices services)
{
_services = services;
_notifier = services.Notifier;
_contentManager = services.ContentManager;
_transactionManager = services.TransactionManager;
}
public ActionResult Create()
{
var company = _contentManager.New<CompanyPart>("Company");
var model = _contentManager.BuildEditor(company);
return View(model);
}
[HttpPost, ActionName("Create")]
public ActionResult CreatePOST()
{
var contentItem = _contentManager.New<CompanyPart>("Company");
var model = _contentManager.UpdateEditor(contentItem, this);
if (!ModelState.IsValid)
{
_transactionManager.Cancel();
return View(model);
}
_contentManager.Create(contentItem.ContentItem);
_notifier.Information(T("Company has been saved"));
return RedirectToAction("Index");
}
public ActionResult Edit(int Id)
{
var contentItem = _services.ContentManager.Get(Id);
dynamic model = _services.ContentManager.BuildEditor(contentItem);
return View(model);
}
[HttpPost, ActionName("Edit")]
public ActionResult EditPOST(int Id)
{
var contentItem = _contentManager.Get<CompanyPart>(Id);
var model = _contentManager.UpdateEditor(contentItem, this);
_notifier.Information(T("Company has been saved"));
return RedirectToAction("Index");
}
public ActionResult Delete(int Id)
{
var contentItem = _contentManager.Get<CompanyPart>(Id);
_contentManager.Destroy(contentItem.ContentItem);
return RedirectToAction("Index");
}
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties)
{
return TryUpdateModel(model, prefix, includeProperties, excludeProperties);
}
public void AddModelError(string key, LocalizedString errorMessage)
{
ModelState.AddModelError(key, errorMessage.ToString());
}
}
View (create)
#{ Layout.Title = T("Add Company").ToString(); }
#using (Html.BeginFormAntiForgeryPost())
{
#Display(Model)
}
Editor Template
#model SDS.Models.CompanyPart
<fieldset>
#Html.LabelFor(m => m.CompanyName)
#Html.TextBoxFor(m => m.CompanyName)
</fieldset>
#*
What goes here to display UserPart?
*#
So here's where I'm at. I can see the ContentItem (CompanyType). I can put in the name and save it. The name is getting saved to the db. Right now the UserPart is getting saved to the db, but all of the fields are blank.
The part I'm stuck on is what to put in the editor template to display the UserPart fields so that the values get to the UserPart driver and ultimately the db.
Any ideas on how to do that?
Thanks!
So you don't attach parts to parts, you attach parts to content items, and you can do that in multiple ways.
You can do it through the admin screen, but that isn't a code driven solution and would have problems if you have multiple environments or need to redeploy a fresh version of code.
You can attach the part when you create a new content item in the migration. This might be a good solution, if you already ran your migration you could possibly do it with an update migration. This allows the part to be managed through the admin screen, but has downsides because it can be removed and if you have code that relies on the part then you will start having errors.
The last way and best way is to attach the part dynamically using an Activating Filter.
ActivatingFilter class - Attaches a part to a content type from code. As opposed to attaching parts via migrations, parts attached using this filter will neither be displayed in the Dashboard, nor users will be able to remove them from types. It's a legitimate way of attaching parts that should always exist on a given content type.
So to do this:
1. Add a reference to Orchard.Users to your custom project.
2. Create a handler for you part. Such as MyPartHandler
3. Then add the activating handler like so
Filters.Add(ActivatingFilter.For<UserPart>("MyContentType"));
So now anywhere in your code you can access the UserPart if you already have your part, or the content item using
var userPart = myPart.As<UserPart>();
I'm an Orchard newbie and I'm having difficulty trying to get the form data when a new item is created.
What I have is a module that creates a menu item on the admin dashboard. That menu item will load a page where a user can enter a new "Coach".
There are 3 things needed for a coach, first name, last name and email.
Here's the code I have implemented for this...
migrations.cs
public class SDSDataMigration : DataMigrationImpl
{
public int Create()
{
SchemaBuilder..CreateTable("CoachPartRecord", table => table.ContentPartRecord()
.Column("FirstName", DbType.AnsiString, c => c.WithLength(50))
.Column("LastName", DbType.AnsiString, c => c.WithLength(50))
.Column("Email", DbType.AnsiString, c => c.WithLength(200)))
ContentDefinitionManager.AlterPartDefinition("CoachPart", part => part
.WithField("FirstName", f => f.OfType("TextField"))
.WithField("LastName", f => f.OfType("TextField"))
.WithField("Email", f => f.OfType("TextField"))
);
ContentDefinitionManager.AlterTypeDefinition("Coach", type => type.WithPart("CommonPart")
.WithPart("CoachPart"));
return 1;
}
}
parts/records
public class CoachPartRecord : ContentPartRecord
{
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual string Email { get; set; }
}
public class CoachPart : ContentPart<CoachPartRecord>
{
public string FirstName
{
get { return Record.FirstName; }
set { Record.FirstName = value; }
}
public string LastName
{
get { return Record.LastName; }
set { Record.LastName = value; }
}
public string Email
{
get { return Record.Email; }
set { Record.Email = value; }
}
}
view for creating editor
#{ Layout.Title = T("Add Coach").ToString(); }
#using (Html.BeginFormAntiForgeryPost()) {
// Model is a Shape, calling Display() so that it is rendered using the most specific template for its Shape type
#Display(Model)
}
handler
public class CoachPartHandler : ContentHandler
{
public CoachPartHandler(IRepository<CoachPartRecord> repository)
{
Filters.Add(StorageFilter.For(repository));
}
}
driver
protected override DriverResult Editor(CoachPart part, IUpdateModel updater, dynamic shapeHelper)
{
updater.TryUpdateModel(part, Prefix, null, null);
return Editor(part, shapeHelper);
}
controller (for dashboard menu item)
public ActionResult Create()
{
var coach = _services.ContentManager.New("Coach");
var model = _services.ContentManager.BuildEditor(coach);
return View(model);
}
[HttpPost, ActionName("Create")]
public ActionResult CreatePOST()
{
var contentItem = _services.ContentManager.New("Coach");
_services.ContentManager.Publish(contentItem);
return View("Index");
}
Right now I can get the form to appear to create a new coach. When I hit "Publish" all of the fields (i.e. FirstName, LastName, Email) for the CoachPart parameter in the driver are null.
I can look at the http request and I can see the values I put on the form, but they're not making it to the CoachPart.
Any ideas why the CoachPart fields aren't getting filed in?
Thanks!
First of all, you are defining the properties on your own record. Therefore you don't need new textfields attached to your part, so you should remove this:
ContentDefinitionManager.AlterPartDefinition("CoachPart", part => part
.WithField("FirstName", f => f.OfType("TextField"))
.WithField("LastName", f => f.OfType("TextField"))
.WithField("Email", f => f.OfType("TextField")));
Secondly, because you use your custom controller istead of orchard's content controller, you must implement the IUpdateModel and act on it:
[Admin]
public class MyController : Controller, IUpdateModel {
private readonly IContentManager _contentManager;
private readonly ITransactionManager _transactionManager;
public MyController(IContentManager contentManager,
ITransactionManager transactionManager) {
_contentManager = contentManager;
_transactionManager = transactionManager;
}
[HttpPost, ActionName("Create")]
public ActionResult CreatePOST()
{
var contentItem = _contentManager.New<CoachPart>("Coach");
// The implementation of IUpdateModel is necessary for this next line:
var model = _contentManager.UpdateEditor(contentItem, this);
if (!ModelState.IsValid) {
_transactionManager.Cancel();
return View(model);
}
_contentManager.Publish(contentItem);
return View("Index");
}
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {
return TryUpdateModel(model, prefix, includeProperties, excludeProperties);
}
void IUpdateModel.AddModelError(string key, LocalizedString errorMessage) {
ModelState.AddModelError(key, errorMessage.ToString());
}
}
An admin should be able to create a user and select which role the user belongs to.
My CreateUserViewModel looks like:
public class CreateUserViewModel
{
public string Id { get; set; }
public string Name { get; set; }
public List<ApplicationRole> Roles { get; set; }
}
My controller action looks like:
public ActionResult CreateUser()
{
var model = new CreateUserViewModel();
ApplicationDbContext appDbContext = new ApplicationDbContext();
// this is the part that doesn't work because of the following error:
// Error 1
// Cannot implicitly convert type
// 'System.Data.Entity.IDbSet<Microsoft.AspNet.Identity.EntityFramework.IdentityRole>'
// to 'System.Collections.Generic.List<AspNetMvcProject.Models.ApplicationRole>'.
// An explicit conversion exists (are you missing a cast?)
model.Roles = appDbContext.Roles;
return View();
}
The main purpose of this is to be able to get the list of roles available so that the admin creating the user can select which roles the user should belong in a <select> element.
You need to convert the list of roles from your Entity Framework DBSet (Microsoft.AspNet.Identity.EntityFramework.IdentityRole) into blb_pgin_bprp.Models.ApplicationRole instances.
One way you could this is like so:
public ActionResult CreateUser()
{
var model = new CreateUserViewModel();
ApplicationDbContext appDbContext = new ApplicationDbContext();
model.Roles = appDbContext.Roles.Select(r => new lb_pgin_bprp.Models.ApplicationRole { Id = r.ID, Name = r.Name }).ToList();
return View();
}
You use Select on the database roles to create instances of your ApplicationRole, picking out the ID and Name
EDIT:
You may need to do something like:
public ActionResult CreateUser()
{
var model = new CreateUserViewModel();
ApplicationDbContext appDbContext = new ApplicationDbContext();
var rolesFromDb = appDbContext.Roles.ToList();
model.Roles = rolesFromDb.Select(r => new lb_pgin_bprp.Models.ApplicationRole { Id = r.ID, Name = r.Name }).ToList();
return View();
}
I am writing my first web API controller so I am a bit of a noob in this area. I am trying to retrieve a list of data through a static class called CustomerDataSource:
public static class CustomerDataSource
{
public static List<Customer> customerData
{
get
{
Customer customer1 = new Customer() { name = "Bert", address = "London" };
Customer customer2 = new Customer() { name = "Jon", address = "New York" };
List<Customer> listCustomers = new List<Customer>();
listCustomers.Add(customer1);
listCustomers.Add(customer2);
return listCustomers;
}
}
}
public class Customer
{
public string name { get; set; }
public string address { get; set; }
}
I am a bit stuck with my ApiController because I am trying to sort the list either on 'name' or 'address' but using a string called 'field' does not compile. What would be a good implementation for a WebAPI controller GETmethod which provides for sorting on one of the Customer properties ?
public class ValuesController : ApiController
{
// GET api/values
public List<Customer> Get(string field)
{
var list = CustomerDataSource.customerData.OrderBy(field);
}
}
Create an extension method like below, then you can use it anywhere within the same namespace in your project.
public static class extensionmethods
{
public static IQueryable<T> OrderByPropertyName<T>(this IQueryable<T> q, string SortField, bool Ascending)
{
var param = Expression.Parameter(typeof(T), "p");
var prop = Expression.Property(param, SortField);
var exp = Expression.Lambda(prop, param);
string method = Ascending ? "OrderBy" : "OrderByDescending";
Type[] types = new Type[] { q.ElementType, exp.Body.Type };
var rs = Expression.Call(typeof(Queryable), method, types, q.Expression, exp);
return q.Provider.CreateQuery<T>(rs);
}
}
Then you can use it like:
public List<Customer> Get(string PropertyName)
{
var list = CustomerDataSource.customerData.AsQueryable().OrderByPropertyName("PropertyName",true).ToList();
}
Note:
Because the extension method uses IQueryable and returns IQuerybale, so you need to convert your List to IQueryable. Also you can order the list by ascending and descending order, just pass the boolean type value to the second parameter. The default is ascending.
You need to use a lambda expression.
if (field == "name")
var list = CustomerDataSource.customerData.OrderBy(d => d.name);
else if (field == "address")
var list = CustomerDataSource.customerData.OrderBy(d => d.address);
Hi all i have a string like this which i am passing an ajax function to my controller action method
Brand1~1001=>undefined_undefined|
Category1~2001=>1001_Brand1|
Category2~2002=>1001_Brand1|
Product3~3003=>2002_Category2|
Product4~3004=>Product3~3003|
Product5~3005=>2002_Category2|
Product6~3006=>2002_Category2|
and i have an Menus table in db i had added that as an entity model to my project
Menus
[MenuID],[MenuName],[ParentID]
and i have model like this
public class MenuItems
{
public List<MenuItems> GetALL { get; set; }
public int MenuId { get; set; }
public string MenuName { get; set; }
public int parentId { get; set; }
}
now i want to split the string i have and insert into the above table like this
[MenuID],[MenuName],[ParentID]
1001 ,Brand1 ,null
2001 ,category1 ,1001
2002 ,category2 ,1001
3003 ,product3 ,2002
3004 ,product4 ,3003
3005 ,product5 ,2002
3006 ,product6 ,2002
in the above string Brand1~1001=>undefined_undefined| here Brand1~1001 is the parentmenu and 1001 is the id of the menu
Category1~2001=>1001_Brand1| and here Category1~2001 is the sub menu of the 1001_Brand1 i think you all got waht i amtrying to do can any one help me here please
what i amtrying
public ActionResult MenuDrag()
{
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult MenuDrag(string menustring)
{
if (!String.IsNullOrEmpty(menustring))
{
string[] menus = menustring.Split('|');
foreach (var m in menus)
{
string[] list = m.Split('>');
//stuck from here confused what to do next and how do i insert the data in my accordingly
}
}
return View();
}
You are almost there just replace your post method with this
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult MenuDrag(string menustring)
{
MenuItems items = new MenuItems();
//check the string for empty
if (!String.IsNullOrEmpty(menustring))
{
string[] menus = menustring.Split('|');
foreach (var m in menus)
{
if (m != "")
{
string[] list = m.Split('>');
string[] menu = list[0].Split('~');
string[] parents = list[1].Split('~');
items.MenuItemID = Convert.ToInt16(menu[1]);
items.MenuName = menu[0].ToString();
if (parents[0] == "undefined")
{
items.ParentID = 0;
db.MenuItems.Add(items);
db.SaveChanges();
}
else
{
int parentid=Convert.ToInt16(parents[0]);
var menuid = from me in db.MenusMains where me.MenuItemID == parentid select new { MenuID = me.MenuID };
foreach (var id in menuid)
{
items.ParentID = Convert.ToInt16(id.MenuID);
}
db.MenuItems.Add(items);
db.SaveChanges();
}
}
}
}
return View();
}
}
i had used
if (m != "")
{
}
since u may get an index out of bound exception there since when in your string at this
string[] menus = menustring.Split('|');
u will get an empty ('|') you have to handle this
hope this works