Database change notification to signalr via mvc4 controller - c#

I have created a NerdDinner like application using the NerdDinner tutorial available online by ScottGu. I want to add SignalR to my application such that every time a new dinner is created, the value of dinners displayed on the home page should be updated.
I have a create method in my HomeController
[HttpPost]
public ActionResult Create(Dinner dinner)
{
if (ModelState.IsValid)
{
nerdDinners.Dinners.Add(dinner);
nerdDinners.SaveChanges();
}
return RedirectToAction("Index");
}
And my Hub class is as below:
[HubName("DinnerHub")]
public class NewDinnerHub : Hub
{
int dinnerCount = 0;
NerdDinners.Models.NerdDinners nerdDinners = new NerdDinners.Models.NerdDinners();
public void SendDinnerNumber(int no_of_dinners)
{
var dinners = from d in nerdDinners.Dinners
select d;
dinnerCount = dinners.ToList().Count();
no_of_dinners = dinnerCount;
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<NewDinnerHub>();
context.Clients.All.getDinnerNumber(this.Context.ConnectionId, no_of_dinners);
}
}
And here is my index.cshtml
#model IEnumerable<NerdDinners.Models.Dinner>
<h2>Index</h2>
<h1>Upcoming Dinners</h1>
<ul>
#foreach(var d in Model) {
<li>
#Html.DisplayFor(modelItem => d.Title)
#Html.DisplayFor(modelItem => d.EventDate)
</li>
}
</ul>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<p>
#Html.Label("Number_of_Dinners","Number of Dinners : ") <label id="No_of_Dinners" />
</p>
<table>
<tr>
<th>
Title
</th>
<th>
EventDate
</th>
<th>
Address
</th>
<th>
HostedBy
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.EventDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.Address)
</td>
<td>
#Html.DisplayFor(modelItem => item.HostedBy)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.DinnerID }) |
#Html.ActionLink("Details", "Details", new { id=item.DinnerID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.DinnerID })
</td>
</tr>
}
</table>
And my javascript which is inside my index.cshtml as well is below
<script>
$(function () {
var hub = $.connection.DinnerHub;
$No_of_Dinners = $("#No_of_Dinners");
hub.client.getDinnerNumber = function (connectionId, no_of_dinners) {
$No_of_Dinners.text = no_of_dinners;
};
$.connection.hub.start().done(function () {
hub.server.sendDinnerNumber($No_of_Dinners);
});
});
</script>
<script src="../../Scripts/jquery-1.7.1.js"></script>
<script src="../../Scripts/jquery-ui-1.8.20.js"></script>
<script src="../../Scripts/jquery.signalR-1.0.1.js"></script>
<script src="/signalr/hubs"></script>
I'm unsure of what is going wrong. I need to update my 'No_of_Dinners' label with the number of dinners in the database whenever a new dinner is added. Also,I'm using .Net MVC4 and I do not want to change my pattern to MVVM. All examples I have seen online are MVVM.
Thanks in advance.

I solved the problem. I wasn't working properly because I did not have my Route.MapHubs() method above RegisterRoutes(). Also, I had to delete bundles/jquery from _Layout.cshtml

Related

Local variable in MVC View

I have an MVC view that displays a list of items. The table that was automatically generated with the view has this action link on every row:
#Html.ActionLink("Delete", "Delete", new { id = item.section_detail_id }).
This works fine but my requirement is to allow the user to highlight a row and click on a delete button at the bottom of the list. I need a way for the button to know which row is currently highlighted. So I created this local variable:
#{int sectionDetailId = 0; }
Then I added an onclick event on the table rows to store the the id of the row that is clicked:
tr id="#item.section_detail_id" onclick="addClass(this.id); sectionDetailId = #item.section_detail_id">
Here is the button that is supposed to bring up the delete view:
input type="button" value="Delete Employee" onclick="location.href='#Url.Action("Delete", "EmployeeList", new { id = sectionDetailId })'; alert(sectionDetailId)" />
The value that is passed to the view is always zero no matter what row is clicked. I added the alert function to the button to show that the variable has the correct value.
Is there a way to get the Action method to use the variable or to get the value from the table in some other way? The Action method works correctly if I hard code an ID.
Here is the complete view:
#model IEnumerable<VCPDS2.Models.EmployeeListViewModel>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<style>
tr.highlight {
background-color: blue !important;
}
</style>
#{int sectionDetailId = 0; }
<h2>Index</h2>
#*<p>
#Html.ActionLink("Create New", "Create")
</p>*#
#if (Model != null)
{
<table id="employeeTable" class="table table-responsive table-striped">
<tr>
<th>
Last Name
</th>
<th>
First Name
</th>
<th>
Employee ID
</th>
<th>
Phone
</th>
<th>
Budget Unit
</th>
<th>
Division
</th>
</tr>
<tbody id="employeeList">
#foreach (var item in Model)
{
<tr id="#item.section_detail_id" onclick="addClass(this.id); sectionDetailId = #item.section_detail_id">
<td>
#Html.DisplayFor(modelItem => item.last_name)
</td>
<td>
#Html.DisplayFor(modelItem => item.first_name)
</td>
<td>
#Html.DisplayFor(modelItem => item.employee_id)
</td>
<td>
#item.phone_nbr
#* #Html.DisplayFor(modelItem => item.phone.area_code) #Html.DisplayFor(modelItem => item.phone.phone_nbr)*#
</td>
<td>
#item.BU
#*#Html.DisplayFor(modelItem => item.phone.BU)*#
</td>
<td>
#item.description
#*#Html.DisplayFor(modelItem => item.department.description)*#
</td>
<td>
#*#Html.ActionLink("Edit", "Edit", new { id = item.section_detail_id }) |
#Html.ActionLink("Details", "Details", new { id = item.section_detail_id }) |*#
#Html.ActionLink("Delete", "Delete", new { id = item.section_detail_id })
</td>
</tr>
}
</tbody>
</table>
<p>
#*#Html.ActionLink("Create New", "Create")*#
<input type="button" value="Add Employee"
onclick="location.href='#Url.Action("Create", "EmployeeList")'" />
<input type="button" value="Delete Employee"
onclick="location.href='#Url.Action("Delete", "EmployeeList", new { id =
#sectionDetailId })'; alert(sectionDetailId)" />
</p>
}
<script src="jquery-3.4.1.min.js"></script>
<script>
function addClass(row) {
//alert(row);
$('#employeeList').children().removeClass('highlight');
var element = document.getElementById(row);
element.classList.add("highlight");
}
</script>
#*#Html.ActionLink("Edit", "Edit", new { id = item.section_detail_id }) |
#Html.ActionLink("Details", "Details", new { id = item.section_detail_id }) |
#Html.ActionLink("Delete", "Delete", new { id = item.section_detail_id
})*#
This is the rendered HTML for the delete button:
<input type="button" value="Delete Employee" onclick="location.href='/EmployeeList/Delete/0'; alert(sectionDetailId)">

How to check if View has received no results

Sorry I didn't really know how to title this.
I have a webpage that displays announcements. What I cant seemed to figure out is whether there are any announcements, if there are display saying "There are no announcements".
I've tried stuff like:
if(db.Announcements.toArray().length == 0){
return View(null);
}
but that doesn't work. Where do I deal with things like these? View/Controller?
View:
#model IEnumerable<Remake.Models.Announcement>
#{
ViewBag.Title = "Announcements";
}
<h2>Announcements</h2>
#if (User.Identity.IsAuthenticated)
{ <p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
<b> #Html.DisplayNameFor(model => model.Title)</b>
</th>
<th>
#Html.DisplayNameFor(model => model.Content)
</th>
<th width="10%">
#Html.DisplayName("Date")
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
<b> #Html.DisplayFor(modelItem => item.Title)</b>
</td>
<td>
#Html.DisplayFor(modelItem => item.Content)
</td>
<td>
<b>#Html.DisplayFor(modelItem => item.PostDate)</b>
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.AnnouncementId }) |
#Html.ActionLink("Comments", "Details", new { id = item.AnnouncementId }) |
#Html.ActionLink("Delete", "Delete", new { id = item.AnnouncementId })
</td>
</tr>
}
</table>
}
else
{
<p>Please sign in to create an Announcement</p>
}
Controller:
// GET: Announcements
public ActionResult Index()
{
return View(db.Announcements.ToList());
}
Since your model is defined as IEnumerable<Announcement>, you can simply use Any() to check whether it's empty or not:
#if (Model.Any())
{
// show announcements
foreach (var item in Model)
{
// ...
}
}
else
{
// show message when empty
<p>No announcements</p>
}
See MSDN

Show the result of an int method in the Index View

I`ve made a simple method to count how many Albums do I have in a table, my only question is simple, I want to show the result of the Count method in the AlbumIndex view. Lets say I want to show a label: "Total" and the number besides it, how do I do this in the View?
This is the method(inside a class called Operations, separated from Controllers and Models):
public int AlbumCounter()
{
int x = db.Albums.Count();
return x;
}
This is the ActionResult Method in my AlbumsController(I don`t know what to do, I want to show the result in the Index View)
public ActionResult AlbumCounter()
{
return
}
and here is the Index View:
#model IEnumerable<AlexMusicStore.Models.Album>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.Artist.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.AlbumName)
</th>
<th>
#Html.DisplayNameFor(model => model.DateCreated)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Artist.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.AlbumName)
</td>
<td>
#Html.DisplayFor(modelItem => item.DateCreated)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.AlbumID }) |
#Html.ActionLink("Details", "Details", new { id=item.AlbumID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.AlbumID })
</td>
</tr>
}
</table>

Accessing a field from a differen't model's table in ASP.NET MVC

I have a page that displays a filtered table based on the user that is passed to the page. I also want to display the user's info a the top of the page, but this comes from a different table (from the Account model). Is there a way I can access fields from this table while working in my other controller/views?
Here is my code:
#{
ViewBag.Title = "User Profile";
}
#model IEnumerable<FTv2.Models.Trade>
#{
ViewBag.Title = "Active Trades";
ViewBag.ImgUrl = ViewBag.Name + ".png";
}
<h2>#ViewBag.User's Profile:</h2>
<p>
// This is where I would like to put the User info.
</p>
<h2>Active Trades:</h2>
<p>
</p>
<table>
<tr>
<th>
</th>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Price)
</th>
<th>
#Html.DisplayNameFor(model => model.User)
</th>
<th></th>
</tr>
#foreach (var item in Model)
{
if (item.User == ViewBag.User)
{
<tr>
<td>
#{ViewBag.ImgUrl = #item.Name + ".png";}
<img src="/Images/#ViewBag.ImgUrl" HEIGHT="66" WIDTH="50" >
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Price) TE
</td>
<td>
#Html.DisplayFor(modelItem => item.User)
</td>
#{if (ViewBag.User == User.Identity.Name){
<td>
#Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
#Html.ActionLink("Details", "Details", new { id = item.ID }) |
#Html.ActionLink("Delete", "Delete", new { id = item.ID })
</td>
}}
</tr>
}
}
</table>
There are two options that I can think of:
Render an action method that returns the user details
#{
Html.RenderAction("UserDetails", new { UserID = ViewBag.UserID});
}
Create a new model that has the user details plus an IEnumerable of the trades and use this for your view.
I suppose that you wanna
make page model that will contain the User Info and IEnumerable<...>.
or pass User info into ViewBag
or call #Html.RenderAction()
I think that you need to keep in mind the chance of reuse of the view model class. If you see no way to reuse the model then use ViewBag to pass the info into a View. In the Controller's Action set the property ViewBag.UserInfo = userInfo; and in the view call: code#Html.Partial("_UserInfo", (UserInfo)ViewBag.UserInfo)code.
But more practical way is to call #Html.Action():
1. Make action UserController.UserInfo(int id).
2. Call from your view #Html.Action("UserInfo", "User", new {Id = ViewBag.UserId});
3. create partial view for the UserController.UserInfo action.

MVC 4 How to pass an object to partial view when list item is clicked?

This is a controller
public class ProductController : Controller
{
//
// GET: /Product/
public ActionResult Index(int id = 0)
{
return View(DALCategory.GetCategoryList());
}
public PartialViewResult productPartial(int id)
{
if (id > 0)
{
return PartialView("_productPartial", DALProduct.GetProductListByCateDetail(id));
}
else
{
return PartialView("_productPartial", DALProduct.GetProductList());
}
}
This is code in index view
#model IEnumerable<Model.Category>
<h2>Products</h2>
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.name)
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.ActionLink(#item.name, "productPartial", new { id = item.id })
</td>
</tr>
}
</table>
#Html.Partial(productPartial)
And this is code for partial view.
#model IEnumerable<Model.Product>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.SKU)
</th>
<th>
#Html.DisplayNameFor(model => model.product_name)
</th>
<th>
#Html.DisplayNameFor(model => model.price)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.SKU)
</td>
<td>
#Html.DisplayFor(modelItem => item.product_name)
</td>
<td>
#Html.DisplayFor(modelItem => item.price)
</td>
<td>
#* #Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })*#
</td>
</tr>
}
</table>
So what I want to do is... when an item is clicked, it renders the partial with an new object. Yes, the partial view is only rendered on the same page.
I have been doing so many things. Although I do not think it is such a hard problem, I am not really sure what I need to do for this...
Since you want to update a part of the page you will need to use ajax to accomplish that. You have two options there:
User #Ajax.ActionLink (How can i load Partial view inside the view)
You can write your own jquery ajax request that invokes your controller method and returns the partial view.
It happened to me as well. I wanted the page to be partial and loaded on the same page but it kept forwarding me to other link. Make sure following points are taken care of:
You have included your jquery-1.6.2.js or whatever version of this file you have.
Also make you have included your jquery file you have created. Make sure the above one is included first.
If you have included these files in some section of your .cshtml section then make sure you render it in your _Layout.cshtml or other layout file you are using. For example you have included your file in head section of your index.cshtml like this
#section head{
}
then you have to render this section in _layout.cshtml with #RenderSection("head", required: false)
what you can also do is Make sure that jQuery is not included twice and that you don't have some javascript errors. Look at your javascript console in the browser as well as the Network tab to ensure that all your scripts are included properly.
Good Luck!!!

Categories