Dynamic link issue in an MVC 3 website
I'm creating my first ASP.NET MVC 3 website for my company's intranet. It's a pretty cool, I play audio recorded by our phone system and saved in our db. That's working good, but I'm having a hard time figuring out how to do something that should be simple. Please forgive any syntax errors I most likely have, this is a rough draft.
I have a table in the Index View /Apps that list all the AppName's, and next to each AppName I want to display a link to another view, with the text of the link being a Count() of all CallDetails associated with that App.
I have two classes:
public class Apps
{
public int AppId { get; set; }
public string AppName { get; set; }
}
public class CallDetail
{
public int Id { get; set; }
public int AppID { get; set; }
public byte[] FirstName { get; set; }
public byte[] LastName { get; set; }
....etc
}
a context for each:
public class AppsContext : DbContext
{
public DbSet<Apps> Apps { get; set; }
}
public class CallC开发者_如何学JAVAontext : DbContext
{
public DbSet<CallDetail> CallDetails { get; set; }
}
a controller method for each:
// AppsController
private AppsContext db = new AppsContext();
public ViewResult Index()
{
return View(db.Apps.ToList());
}
// CallController method (from my current attempt)
public ActionResult CallCheck(int id)
{
bool? enabled = null;
var appcalls = from s in db.CallDetails
where s.AppID == id
&& s.Enabled.Equals(enabled)
select s;
string callnum = appcalls.Count().ToString();
return View(callnum);
}
It displays the AppName just fine in this portion of the View below, and I can create a link to a View for each associated CallDetail just fine. But I don't know how to display info I'd get from the CallDetail Controller since the View's Model is Apps and its Controller, AppsController.
@model IEnumerable<myMessagePlayer.Models.Apps>
...
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.AppName)
</td>
<td class="appLink">
...
</td>
</tr>
}
I've tried many different methods, some that I might have gotten to work, but they seemed semantically un-MVC. So I figured I'd just ask a general "whats the standard practice?" type of question.
The path you are currently going down would end up hitting the database for each app you have in your database. There is a way to display all the information with only one hit to the database.
Your context needs to change to this:
public class ApplicationContext : DbContext
{
public DbSet<Apps> Apps { get; set; }
public DbSet<CallDetail> CallDetails { get; set; }
}
You could create a view model object called AppCallInfo that has three properties:
public class AppCallInfo
{
public int AppID { get; set; }
public string AppName { get; set; }
public int CallCount { get; set; }
}
In your Index action you need to do something like this:
public ViewResult Index()
{
var model = from a in db.Apps
join c in db.CallDetails on a.AppID equals c.AppID
where c.Enabled == enabled
group a by new { AppName = a.AppName, AppID = a.AppID } into g
select new AppCallInfo {
AppName = g.Key.AppName,
AppID = g.Key.AppID,
CallCount = g.Count()
};
return View(model.ToList());
}
Now you have everything you need for each row in your table in one object.
@model List<myMessagePlayer.ViewModels.AppCallInfo>
...
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.AppName)
</td>
<td class="appLink">
@Html.ActionLink(item.CallCount, "ViewCalls", "Call", new { Id = item.AppID }, null)
</td>
</tr>
}
Using this method avoids hitting the database for each app you have in your table.
Is the view CallCheck a partial view?
In your index view you could use
@Html.RenderAction("CallCheck", "AppsController", new { Id = @Model.AppId } )
The syntax may not be 100% correct, but it should get you going in the right direction.
精彩评论