For my company, we are building a web application for an invoicing system which utilises a notification bar, similar to that of Facebook, whereby the user can drop down a menu which displays the status of transactions on the system while a total number of outstanding transactions displays next to it. Please see the image for details.
http://img210.imageshack.us/img210/4379/alertdrop.png
We are retrieving the data for this using the following code for the table within the drop-down menu:
<table id="alertDropTable" style="margin-top:10px;">
@{
Dictionary<string, int> dic = ViewBag.statusCount;
if (dic != null)
{
for (int i = 0; i < dic.Count; i++)
{
if (dic.Values.ElementAt(i) > 0)
{
<tr>
<td width="100%" style="padding-bottom:4px; padding-top:4px; padding-left:10px; padding-right:10px; vertical-align:middle;">
You have <strong><a style="background-color:#878787; border-radius:5px; color:White; padding:3px;">@dic.Values.ElementAt(i)</a></strong> @dic.Keys.ElementAt(i) transaction(s).
</td>
</tr>
}
}
}
}
</table>
And the following for the span, which displays the total:
<div style="float: left;">
<a href="javascript:;" onmouseover="document.alert.src='@Url.Content("~/Content/images/alert_notification_hover.png")'" onmouseout="document.alert.src='@Url.Content("~/Content/images/alert_notification.png")'" onclick="toggle('notificationDrop');"><img src="@Url.Content("~/Content/images/alert_notification.png")" name="alert" alt="alert"/></a>
@{
Dictionary<string, int> dicheader = ViewBag.statusCount;
int diccount = 0;
if (dicheader != null)
{
for (int i = 0; i < dicheader.Count; i++)
{
if (dicheader.Values.ElementAt(i) > 0)
{
diccount = diccount + @dicheader.Values.ElementAt(i);
}
}
}
}
</div>
<div id="alertTotalDiv" style="float:left;margin-top:6px; margin-left:5px;"><span id="alertTotal" style="vertical-align:middle; background-color:#878787; border-radius:5px; color:White; font-family:Georgia; font-size:20px; padding:3px; padding-left:5px; padding-right:5px;margin-top:0px;">@diccount</span></div>
This code is currently stored in the global “_layout.cshtml” file. Please excuse the roughness of the code, this is very much an early version. However, this is working fine in terms of retrieving the data on a page load. However, the system requires this information to be automatically updated every few seconds without refreshing the entire page. In essence, making a call to the controller to bring back the current data and update the <table> and <span> with the current values.
I have been asked to create an Ajax function which retrieves the data from the “AlertController” and updates the view accordingly. Please find the contents of this controller below:
public class AlertController : Controller
{
/// <summary>
/// Gets or sets the user service contract.
/// </summary>
/// <value>The user service contract.</value>
public IUserServiceContract UserServiceContract { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="BaseController"/> class.
/// </summary>
protected AlertController()
{
this.UserServiceContract = Gateway.Instance.Resolve<IUserServiceContract>();
}
/// <summary>
/// Get the AlertTypes
/// </summary>
/// <returns></returns>
public virtual void ViewAlerts()
{
Gateway.Instance.Logger.LogInfo(string.Format("Overview Controller View: Fetching list of alerts."));
try
{
if (this.UserServiceContract != null)
{
var allAnnouncements = this.UserServiceContract.GetAnnoucements();
var userAlertSettings = this.UserServiceContract.GetUserAlert();
ViewBag.statusCount = userAlertSettings;
ViewBag.announcements = allAnnouncements.ToList();
}
}
catch (Exception ex)
{
Gateway.Instance.Logger.LogInfo(ex);
throw new Exception(string.Format("Home Controller View Error: {0} occured while fetching alerts.", ex.Message), ex);
}
}
I am stumped, but have been given the following example of an Ajax function, which is used to perform a different task entirely, to aid me:
$.ajax({
url: '@Url.Action("ViewAlerts", "Alerts")',
data: { ownerIds: ownerIds },
traditional: true,
dataType: 'json',
success: function (result) {
for (i = 0; i < ownerIds.length; i++) {
$(".ownersTable tr[id='tablerow+" + ownerIds[i] + "']").remove();
}
},
error: function (xhr, ajaxOptions, thrownError) {
$("#confirmDiv").alertModal({
heading: '@Language.Fail',
body: '@Language.AlertRemoveOwnerFailed' + thrownError
});
}
});
Thus far, the only thing I’ve managed to get working was a set interval function, which makes an alert every 5 seconds!
Any guidance on this?
Okay, this is what you are going to need to do, first of all:
Why is Url.Action in quotes? Just put @Url.Action … I don’t see a reason for the quotes and it may be breaking your call.
Second of all don’t use ViewBag. It shouldn’t be really used to hold ‘data’ (in my opinion). You should use a model. So this is what you can do:
Create the part of the page you want to update into a “Partial View” that is strongly typed to a model that contains the status and announcements and whatever else you need.
Use Jquery to ‘Load’ the Controller method that will get the data and return this ‘Partial View’, and load it into a Div on your screen example:
So your controller is then called, gets the data and returns the partial view with the model you created!
Good luck!
—Edit— YOU should do above because it would be easier and faster (and if you do get to redesign you will quickly understand that, but here is an idea of how to do what you want)
This is what you need to know,
url is the action that the Ajax is going to call. You need to put url: ‘/controller/action’
data is the data you are sending to that action { parameter-name: parameter } it looks like in your case your sending no data because your only polling for a refresh, so you don’t need to include this
dataType is the data you are expecting to be returned, it could be ‘html’ or ‘json’ , in your case your returning nothing because your using the ‘ViewBag’
success will be called if the ajax call was successfully called with no errors with the result of that in ‘result’, in your case you have no result, because your using the view bag.
Now I can’t promise this will work because I have never tried it:
Inside your success function on the ajax try this, this may or may not work. I honestly don’t know if the ViewBag will have the updated values or not. At this point you only need to replace the table values with your new ones! you’ll have to do all that in javascript, and I suggest looking at functions like ‘appendTo’, ‘replaceWith’, ‘html’ ect that are in Jquery to figure out how to do that.