I got an ActionResult TabNotes which returns a View for a tab which shows notes from a database in a grid. On the tab is a button for ActionResult CreateNote, which returns a PartialView and after saving the note I redirect back to the ActionResult TabNotes with
return RedirectToAction("TabNotes", new { modelEntity = "Phrase", id = itemId});
However, when it goes to the action result TabNotes using this redirect it does not show the grid. The javascript gives the following error
Uncaught ReferenceError: $ is not defined (anonymous function)
Uncaught ReferenceError: ko is not defined (anonymous function)
This does not happen the first time it goes to ActionResult. Using breakpoints the following part of the ActionResult TabNotes:
[...]
Model.Grid.url = Url.Action("TabNoteData", new { id = Model.meta.entity, itemId = Model.meta.id.Value});
}
return View("TabNotes", Model);
}
gives the same input values in Model for the first time and the second time. Where can this error come from?
Edit: Firebug shows the following errors:
prompt aborted by user
throw Components.Exception...by user", Cr.NS_ERROR_NOT_AVAILABLE); nsPrompter.js (regel 462 <Systeem>
$ is not defined
$(document).ready(function(){$('#tblTN...tes/44?cmd=refresh" id="TNPhrase44"> 44?mod...=Phrase (regel 2)
ko is not defined
var viewModel=ko.mapping.fromJ...],"buttons":[],"PostAction":null}}); 44?mod...=Phrase (regel 12)
Below is the javascript and code
#model test.Web.Framework.Areas.Administration.Models.TabNotesModel
#using (UI.DocumentReadyScript())
{
if (Model.meta.id.HasValue)
{
UI.jQuery("#tbl" + Model.meta.modelname).flexigrid(Model.Grid);
}
}
<form method="post" action="#Url.Action("TabNotes", new { cmd = "refresh" })" id="#Model.meta.modelname">
<div class="ui-state-highlight ui-corner-all highlight" data-bind="visible: meta.message">
<span class="ui-icon ui-icon-info"></span><strong data-bind="text: meta.message">
</strong>
</div>
#using (UI.BeginBlock("Administation.TabNotes", UI.Label("Notes", "Notes").ToString(), test.Web.Framework.Core.enumIcons.pencil, false, false))
{
<table id="#("tbl" + Model.meta.modelname)">
</table>
}
</form>
<script type="text/javascript">
(function() {
var viewModel=ko.mapping.fromJS(#Html.Raw(UI.JavascriptEncode(Model)));
viewModel.getData=function() { return ko.mapping.toJSON( this ); };
viewModel.setData=function(data){
$('#tbl'+this.meta.modelname()).flexigrid( data.Grid);
ko.mapping.updateFromJS(this,data);
};
$('##Model.meta.modelname').koform({viewmodel: viewModel , validate : {errorElement:'p' } } );
$('##Model.meta.modelname').koform('applyBindings');
$('#load-partial').click(function() {
$('#partial').load('#Url.Action("CreateNote", "Entity", new {itemId = #Model.meta.id, modelEntity = "Phrase"})');
});
})();
</script>
<div id="partial"></div>
<button type="button" id="load-partial">Create Note</button>
'
public ActionResult CreateNote(
[ModelBinder(typeof(Models.JsonModelBinder))]
NoteModel Model, string cmd, long? itemId, string modelEntity)
{
if (cmd == "Save")
{
Model.meta.message = "Note saved";
test.Database.User User = UserRepository.GetUser(1);
Entity entity = NotesRepository.GetEntity("Phrase");
NotesRepository.StoreNote(Model.subject, Model.text, User, entity, itemId);
return RedirectToAction("TabNotes", new { modelEntity = "Phrase", id = itemId});
}
Model.meta.modelname = "CreateNote";
Model.meta.JsViewModelType = "EditNoteModel";
Model.meta.PostAction = Url.Action("CreateNote", new { cmd = "Save", itemId = itemId});
return PartialView("CreateNotePartial",Model);
}
'
public ActionResult TabNotes([ModelBinder(typeof(Models.JsonModelBinder))]
TabNotesModel Model, string cmd, string modelEntity, long? id)
{
if (modelEntity != null)
{
Model.meta.entity = modelEntity;
}
Entity entity = NotesRepository.GetEntity(Model.meta.entity);
if (id.HasValue)
{
Model.meta.id = id;
}
if (Model.meta.id.HasValue)
{
Model.meta.modelname = "TN" + Model.meta.entity + Model.meta.id.Value.ToString();
Dictionary<string, object> defaultValues = new Dictionary<string, object>();
defaultValues.Add("Entity", entity.EntityId);
defaultValues.Add("ItemId", Model.meta.id.Value);
Entity noteEntity = NotesRepository.GetEntity("Note");
var grid = UI.GetEntityFlexiGrid(noteEntity, true, true, true, true, defaultValues);
grid.buttons.Clear();
//grid.buttons.Add(new Button { onpress = "CreateNote", action = Url.Action("CreateNote"), name = "CreateNote", postdata = new { meta = Model.meta }});
grid.title = "";
Model.Grid = grid;
Model.Grid.url = Url.Action("TabNoteData", new { id = Model.meta.entity, itemId = Model.meta.id.Value});
}
return View("TabNotes", Model);
}
'
public GridResult TabNoteData(string id, long itemId, FlexigridRequest request, string cmd)
{
GridResult returnValue = null;
var entity = NotesRepository.GetEntity(id);
Entity noteEntity = NotesRepository.GetEntity("Note");
//var Acess = UIRepository.GetEntityAccess(id);
FlexigridConfiguration grid;
Dictionary<string, object> defaultValues = new Dictionary<string, object>();
defaultValues.Add("Entity", entity.EntityId);
defaultValues.Add("ItemId",itemId);
grid = UI.GetEntityFlexiGrid(noteEntity, true, true, true, true, defaultValues);
IQueryable q = NotesRepository.GetNotes(entity.EntityId, itemId);
var sortField = entity.EntityFields.SingleOrDefault(c => c.Name == request.sortname);
if (sortField == null)
{
request.sortname = grid.sortname;
}
IQueryable qdata = null;
if (!string.IsNullOrEmpty(request.sortname) && request.sortname != "undefined")
{
switch (request.sortorder)
{
case enumFlexigridRequestSortOrder.asc:
qdata = q.OrderBy(request.sortname + " ascending");
break;
case enumFlexigridRequestSortOrder.desc:
qdata = q.OrderBy(request.sortname + " descending");
break;
}
}
if (!string.IsNullOrEmpty(request.query) && !string.IsNullOrEmpty(request.qtype))
{
qdata = qdata.Where(request.qtype.SanitizeFieldExpression() + ".Contains(#0)", request.query);
}
if (request.q != null && request.q.Length > 0)
{
for (int i = 0; i < request.q.Length; i++)
{
var type = UIRepository.GetType(id);
var property = type.GetProperty(request.q[i]);
System.ComponentModel.TypeConverter tc = System.ComponentModel.TypeDescriptor.GetConverter(property.PropertyType);
string sv = request.v[i];
if (sv == null || sv == "null")
{
qdata = qdata.Where(request.q[i].SanitizeFieldExpression() + "=#0", (object)null);
}
else
{
object v = tc.ConvertFromString(sv);
qdata = qdata.Where(request.q[i].SanitizeFieldExpression() + "=#0", v);
}
}
}
string settingName = "Grid." + id + ".Rp";
var setting = UIRepository.GetQuery<test.Database.UserSetting>().SingleOrDefault(uc => uc.CreatedById == CurrentUser.UserId && uc.Name == settingName);
if (setting == null)
{
setting = UIRepository.Create<test.Database.UserSetting>();
setting.Name = settingName;
setting.Value = request.rp.ToString();
UIRepository.Add(setting);
}
else
{
if (request.rp.ToString() != setting.Value)
{
setting.Value = request.rp.ToString();
UIRepository.Update(setting);
}
}
int rowId = 0;
var datarows = new List<object>();
foreach (var record in qdata.Skip((request.page - 1) * request.rp).Take(request.rp).GetData())
{
var cellValues = new List<object>();
foreach (var gc in grid.colModel.OrderBy(c => c.di))
{
cellValues.Add(gc.ToString(UI, record));
}
var row = new { id = rowId, cell = cellValues.ToArray() };
datarows.Add(row);
rowId++;
}
returnValue = Grid(request.page, qdata.Count(), datarows.ToList());
return returnValue;
}
That error can only be caused be one of three things:
Your JavaScript file is not being properly loaded into your page
You have a botched version of jQuery. This could happen because someone edited the core file, or a plugin may have overwritten the $ variable.
You have JavaScript running before the page is fully loaded, and as such, before jQuery is fully loaded.
You should check the Firebug net panel to see if the file is actually being loaded properly. If not, it will be highlighted red and will say "404" beside it. If the file is loading properly, that means that the issue is number 2.
Make sure all javascript code is being run inside a code block such as:
$(document).ready(function () {
//your code here
});
This will ensure that your code is being loaded after jQuery has been initialized.
One final thing to check is to make sure that you are not loading any plugins before you load jQuery. Plugins extend the "$" object, so if you load a plugin before loading jQuery core, then you'll get the error you described.
So to avoid that you can use a "bodyguard" function like the following:
( function($) {
//We can now use $ as I implemented the bodyguard!
$(document).ready(function() {
//your code...
});
} ) ( jQuery );
Related
My project has models with 2 or more words in the name:
EngineConfigurationModel
MyProductModel
CurrentProductModel
CheckNetworkInventoryModel
I've got an extension that can create a breadcrumb:
public static string BuildBreadcrumbNavigation(this HtmlHelper helper)
{
// optional condition: I didn't wanted it to show on home and account controller
if (helper.ViewContext.RouteData.Values["controller"].ToString() == "Home" ||
helper.ViewContext.RouteData.Values["controller"].ToString() == "Account")
{
return string.Empty;
}
var htmlLink = helper.ActionLink("Home", "Index", "Home").ToHtmlString();
var sb = new StringBuilder("<ol class='breadcrumb'><li>");
sb.Append(htmlLink);
sb.Append("</li>");
sb.Append("<li>");
sb.Append(helper.ActionLink(helper.ViewContext.RouteData.Values["controller"].ToString().Titleize(),
"", // "Index",
helper.ViewContext.RouteData.Values["controller"].ToString()));
sb.Append("</li>");
if (helper.ViewContext.RouteData.Values["action"].ToString() != "Index")
{
sb.Append("<li>");
sb.Append(helper.ActionLink(helper.ViewContext.RouteData.Values["action"].ToString().Titleize(),
helper.ViewContext.RouteData.Values["action"].ToString(),
helper.ViewContext.RouteData.Values["controller"].ToString()));
sb.Append("</li>");
}
var result = sb.Append("</ol>").ToString().Replace("Index", "");
return result;
}
Source: https://stackoverflow.com/a/26439510/153923
But, I want to split-up the words for project models with 2 or more words in the name.
for EngineConfigurationModel, class name EngineConfiguration would be 'Engine Configuration'
MyProductModel, class name MyProduct would be 'My Product'
CurrentProductModel, class name CurrentProduct would be 'Current Product'
CheckNetworkInventoryModel, class name CheckNetworkInventory would be 'Check Network Inventory'
For model properties with multiple words, I can use a [Display(Name = "some thing")] parameter like this:
[Display(Name = "Some Thing")]
public string SomeThing { get; set; }
I tried putting the Display attribute on the class declaration, but VS2022 says:
Attribute 'Display' is not valid on this declaration type. It is only valid on 'method, property, indexer, field, parameter' declarations.
I made something and I put it into an extension. It has gone through 2 revisions, but it seems to be flawless now.
Adding my work here for others:
public static string SplitTitleWords(this string value)
{
var cList = new List<char>();
if (!string.IsNullOrEmpty(value))
{
cList.Add(value[0]); // just add the first letter, whether caps, no caps, or number
for (var i = 1; i < value.Length; i++)
{
var c = value[i];
if (char.IsUpper(c))
{ // 01234567891234 0123456789012345
// check special cases like class AddPDFResource => Add PDF Resource
var c0 = value[i - 1];
if (char.IsUpper(c0))
{
if (i + 1 < value.Length)
{
var c1 = value[i + 1];
if (!char.IsUpper(c1))
{
cList.Add(' ');
}
}
} else
{
cList.Add(' ');
}
}
cList.Add(c);
}
}
var result = new String(cList.ToArray());
return result;
}
And here is a Breadcrumb extension method that calls it twice:
public static string BuildBreadcrumbNavigation(this HtmlHelper helper)
{
var result = string.Empty;
var controllerName = helper.ViewContext.RouteData.Values["controller"].ToString();
// optional condition: I didn't wanted it to show on home and account controller
if ((controllerName != "Home") && (controllerName != "Account"))
{
var homeLink = helper.ActionLink(
linkText: "Home",
actionName: "Index",
controllerName: "Home").ToHtmlString();
var sb = new StringBuilder($"<ol class='breadcrumb'><li>{homeLink}</li>");
var url = HttpContext.Current.Request.Url.ToString();
var urlParts = url.Split(new char[] { '/' });
if (!urlParts.Contains("Console"))
{
var controllerLink = helper.ActionLink(
linkText: controllerName.SplitTitleWords(),
actionName: "Index",
controllerName: controllerName);
sb.Append($"<li>{controllerLink}</li>");
} else
{
var a = $"Console";
sb.Append($"<li>{a}</li>");
}
var actionName = helper.ViewContext.RouteData.Values["action"].ToString();
sb.Append($"<li class=\"active\">{actionName.SplitTitleWords()}</li>");
result = sb.Append("</ol>").ToString();
}
return result;
}
It has been working great for me.
I am looking to implement a Tab Menu that uses the same View and Partial View. But then when you click either of the tabs its updated based on the comparison in the Model. The Controller works out if its an Original or Amendment. So far I have the two tabs showing using:
var fullAccountCodeOriginal = Model.OriginalWriter.ID;
var fullAccountCodeAmendment = Model.ActiveAmendmentWriter.ID;
<div class="page-tabs">
<ul class="nav nav-tabs">
<li class='#((actionName.ToLower() == "viewwriteramendments") &&
controllerName.ToLower() == "songsmanagement" ? "active" : "")'>
<a href='#Url.Action("ViewWriterAmendments", "SongsManagement", new
{
accountcode = fullAccountCodeOriginal
})' data-container="body" data-toggle="tooltip" title="Song Management">Original Track Details</a>
</li>
<li class='#((actionName.ToLower() == "viewwriteramendments") &&
controllerName.ToLower() == "songsmanagement" ? "active" : "")'>
<a href='#Url.Action("ViewWriterAmendments", "SongsManagement", new
{
accountcode = fullAccountCodeAmendment
})' data-container="body" data-toggle="tooltip" title="Song Management">Updated Track Details</a>
</li>
}
</ul>
In the Model is have:
public ViewWriterAmendmentsComparisonModel()
{
this.OriginalWriter = default(WriterAmendmentsComparisionModel);
this.ActiveAmendmentWriter = default(WriterAmendmentsComparisionModel);
}
public WriterAmendmentsComparisionModel OriginalWriter { get; set; }
public WriterAmendmentsComparisionModel ActiveAmendmentWriter { get; set; }
Controller
var writerAndActiveAmendment = new ViewWriterAmendmentsComparisonModel
{
OriginalWriter = new WriterAmendmentsComparisionModel
{
ID = domainWriterAndAmendmentModel.Original.ID,
RowVersion = domainWriterAndAmendmentModel.Original.RowVersion,
IsDeleted = domainWriterAndAmendmentModel.Original.IsDeleted,
IsLocked = domainWriterAndAmendmentModel.Original.IsLocked,
IsNew = domainWriterAndAmendmentModel.Original.IsNew,
Version = domainWriterAndAmendmentModel.Original.Version,
FirstName = domainWriterAndAmendmentModel.Original.FirstName,
MiddleName = domainWriterAndAmendmentModel.Original.MiddleName,
LastName = domainWriterAndAmendmentModel.Original.LastName,
PRO = domainWriterAndAmendmentModel.Original.Society?.Name ?? string.Empty,
CaeIpiNumber = domainWriterAndAmendmentModel.Original.CaeIpiNumber,
IsProMember = domainWriterAndAmendmentModel.Original.IsProMember,
Songs = domainWriterAndAmendmentModel.Original.WriterSplits != null
? domainWriterAndAmendmentModel.Original.WriterSplits
.Select(x => new AssociatedSongsComparisonModel
{
// meta
ID = x.ID,
RowVersion = x.RowVersion,
IsDeleted = x.IsDeleted,
// data
SongTitle = x.RelatedWork.Title,
SongId = x.RelatedWork.UniqueCode,
CreatedDate = x.RelatedWork.CreatedDate,
WriterCount = x.RelatedWork.WorkSplits.Count,
RecordingCount = x.RelatedWork.Recordings.Count
})
.ToList()
: new List<AssociatedSongsComparisonModel>(),
},
ActiveAmendmentWriter = new WriterAmendmentsComparisionModel
{
ID = domainWriterAndAmendmentModel.CurrentAmendment.ID,
RowVersion = domainWriterAndAmendmentModel.CurrentAmendment.RowVersion,
IsDeleted = domainWriterAndAmendmentModel.CurrentAmendment.IsDeleted,
IsNew = domainWriterAndAmendmentModel.CurrentAmendment.IsNew,
FirstName = domainWriterAndAmendmentModel.CurrentAmendment.FirstName,
MiddleName = domainWriterAndAmendmentModel.CurrentAmendment.MiddleName,
LastName = domainWriterAndAmendmentModel.CurrentAmendment.LastName,
PRO = domainWriterAndAmendmentModel.CurrentAmendment.Society?.Name ?? string.Empty,
CaeIpiNumber = domainWriterAndAmendmentModel.CurrentAmendment.CaeIpiNumber,
IsProMember = domainWriterAndAmendmentModel.CurrentAmendment.IsProMember,
Songs = domainWriterAndAmendmentModel.CurrentAmendment.WriterSplitAmendments != null
&& domainWriterAndAmendmentModel.CurrentAmendment.WriterSplitAmendments.Any(x => x.RelatedWorkAmendment != null)
? domainWriterAndAmendmentModel.CurrentAmendment.WriterSplitAmendments
.Select(x => new AssociatedSongsComparisonModel
{
// meta
ID = x.ID,
RowVersion = x.RowVersion,
IsDeleted = x.IsDeleted,
// data
SongId = x.RelatedWorkAmendment.UniqueCode,
SongTitle = x.RelatedWorkAmendment.Title,
CreatedDate = x.RelatedWorkAmendment.CreatedDate,
WriterCount = x.RelatedWorkAmendment.WorkSplitAmendments.Count,
RecordingCount = x.RelatedWorkAmendment.RecordingAmendments.Count
})
.ToList()
: new List<AssociatedSongsComparisonModel>(),
}
};
return writerAndActiveAmendment;
}
[HttpGet]
[ActionName("ViewWriterAmendments")]
[Route("{writercode}/ViewWriterAmendments")]
[AuthorizeTenancy(Roles = "super,administrator")]
public async Task<ActionResult>ViewWriterAmendments(string writercode, int page = 1, int take = Constants.MVC.Pagination.DefaultItemsPerPage, string sortBy = "Name", bool sortAsc = true)
{
if (Request.QueryString["IsAmendment"] != null)
{
ViewBag.IsAmendment = Request.QueryString["IsAmendment"];
}
else
{
ViewBag.IsAmendment = "0";
}
// TEST IF VALID
// ajax method - refuse
if (Request.IsAjaxRequest())
{
return RedirectToAction("WriterAmendments", "SongsManagement");
}
// no writer - refuse
if (string.IsNullOrEmpty(writercode))
{
return RedirectToAction("WriterAmendments", "SongsManagement", new { page, take, sortBy, sortAsc });
}
// get originalWithPossibleActiveAmendment work
var writerAndAmendment = await _artistAccountService.GetWriterAndAmendmentGraphAsync(writercode, includeWritersSplitsAndWorks: true, includeWriterSociety: true);
// not found? - refuse
if (writerAndAmendment.Original == default(WriterGraph.Writer))
{
return RedirectToAction("WriterAmendments", "SongsManagement", new { page, take, sortBy, sortAsc }); // something wrong
}
// writer locked? - refuse
if (writerAndAmendment.Original.IsLocked)
{
return RedirectToAction("WriterAmendments", "SongsManagement", new { page, take, sortBy, sortAsc }); // something wrong
}
// setup view model
var viewModel = MapWriterAndAmendmentToViewModel(writerAndAmendment);
// return view
return View(viewModel);
}
}
}
Is there a way I can get it switch betwwen the two tabs using JQuery or another method, maybe an IF/ELSE in Razor. I am new to MVC.
You can just use jQuery so in Controller you got for example Enum param (if more than 2 cases of data loading) or boolean flag, which content to load. Than based on the parameter you've received you make an if statement inside controller to decide what data you should load. It's pretty simple, I won't give you fish but a rod. Read about overriding in jQuery button on click event and sending ajax requests.
Extra advice. IMHO this looks horrible
<li class='#((actionName.ToLower() == "viewwriteramendments") &&
controllerName.ToLower() == "songsmanagement" ? "active" : "")'>
<a href='#Url.Action("ViewWriterAmendments", "SongsManagement", new
{
accountcode = fullAccountCodeAmendment
})' data-container="body" data-toggle="tooltip" title="Song Management">Updated Track Details</a>
</li>
Passing active class should be done inside jQuery too.
If you create repeatable li elements you could think about making another partial view for them. For 2 it's fine but for more elements create seperate view.
Change the a href to some button and override it's default behavior.
Naming conventions - try to name your ids and classes with some stable convention for whole project.
I have a project where I report time on diffrent projects, and I am working on so I can delete a report incase I do it wrong, which is working decent.
When I go to the summery page of all my reports it lists all the dates, I click the date and it sends it to the TimeReport view like this:
http://localhost:9061/Reports/TimeReport/b604a74a-2034-4916-9534-57788db1e8e2
And than it checks if the ReportId has a value like this:
#if (Model.ReportId.HasValue)
{
<button type="button" class="btn btn-danger" data-toggle="modal" data-target="#basic">Ta bort!</button>
}
And if it exists a Remove button will appear, I click the remove button and it will remove the report. but the URL is still the same, so if I refresh the site my application will crash because it that ID no longer exists in the database.
if (form != null && form.AllKeys.Contains("delete"))
{
new DatabaseLayer().DeleteTimeReport(Guid.Parse(form["ReportId"]));
LoadDefaultSettings(projectData);
ViewData.Model = projectData;
ViewData["deleted"] = true;
return View();
}
This is the model that check if if the GUID exists.
public void SaveToDatabase(Guid consultantId)
{
using (DatabaseLayer db = new DatabaseLayer())
{
//Time report exists, delete it.
if (ReportId.HasValue)
{
db.DeleteTimeReport(ReportId.Value);
}
//Time report does not exist, create a new one.
else
{
ReportId = Guid.NewGuid();
}
Report report = new Report
{
FK_ConsultantID = consultantId,
FK_UserID = Constants.UserTreetop,
Date = Date,
TimeReportID = ReportId.Value
};
TimeReportData reportData = new TimeReportData
{
Absent = 0,
Description = "",
StartHour = Times.StartHour,
StartMinute = Times.StartMinute,
EndHour = Times.EndHour,
EndMinute = Times.EndMinute,
BreakHour = Times.BreakHour,
BreakMinute = Times.BreakMinute,
FK_TimeReportID = ReportId.Value,
TimeReportDataID = Guid.NewGuid()
};
TimeReportProject[] reportProjects = new TimeReportProject[Projects.Count];
for (int i = 0; i < Projects.Count; i++)
{
reportProjects[i] = new TimeReportProject
{
Description = Projects[i].Description,
FK_ProjectID = Projects[i].ProjectId,
FK_TimeReportID = ReportId.Value,
Hours = Projects[i].Hours.GetValueOrDefault(), //Projects[i].Hours.Value,
HourRate = db.GetProjectHourRate(Projects[i].ProjectId, Date, Projects[i].Hours.GetValueOrDefault()),
TimeReportProjectID = Guid.NewGuid()
};
}
db.InsertTimeReport(report, reportData, reportProjects);
}
}
And as it exists it does this
public void DeleteTimeReport(Guid timeReportId)
{
db.ExecuteStoreCommand(
#" DELETE FROM [Salesweb].[dbo].[TimeReportProject] WHERE FK_TimeReportID = #id;
DELETE FROM [Salesweb].[dbo].[TimeReportData] WHERE FK_TimeReportID = #id;
DELETE FROM [Salesweb].[dbo].[TimeReport] WHERE TimeReportID = #id;"
, new SqlParameter("#id", timeReportId));
db.SaveChanges();
}
This is the view when I pass in the guid I Want to delete as the guid has a value the remove button will appear.
But as I delete the project it will return to the same view. Like we can see the tabs is not showing up, so if I want the to show again I have to go to another view, and than back to the same view. And if I refresh it will crash due the guid dosen't exist in the DB.
And here is the whole controller, it's a bit messy right now.
public ActionResult TimeReport(FormCollection form, Guid? id)
{
ViewDataDictionary vd = new ViewDataDictionary
{
["projects"] = new DatabaseLayer().GetConsultantProjects(Constants.CurrentUser(User.Identity.Name)),
["id"] = 1,
["showDescription"] = true
};
ViewData["vd"] = vd;
NewTimeReportModel projectData = new NewTimeReportModel();
if (form != null && form.AllKeys.Contains("delete"))
{
new DatabaseLayer().DeleteTimeReport(Guid.Parse(form["ReportId"]));
LoadDefaultSettings(projectData);
ViewData.Model = projectData;
ViewData["deleted"] = true;
return RedirectToAction("Index");
}
if (id.HasValue && (form == null || form.AllKeys.Length == 0))
{
using (DatabaseLayer db = new DatabaseLayer())
{
var timeReport = db.GetTimeReport(id.Value);
projectData = new NewTimeReportModel(timeReport);
if (projectData.Projects.Count == 1)
projectData.Projects[0].Hours = null;
}
}
else if (form == null || form.AllKeys.Length == 0)
{
LoadDefaultSettings(projectData);
}
else
{
//Get's all the dates from the view and formates them to look like yy-mm-dd so we can parse it to a datetime.
string[] dates = FormateDate(form["date"]);
//Loops over all the dates and saves the dates to the database.
projectData = ReportDates(form, projectData, dates);
//Loads default settings if all dates been reported.
LoadDefaultSettings(projectData);
}
//Get's and lists all the missing days
ListAllMssingDays();
ViewData.Model = projectData;
return View();
}
Recommended thing to do in such cases is run redirect to some default URL, like the summary page. Guessing that you have Summary action, that should be something like:
if (form != null && form.AllKeys.Contains("delete"))
{
new DatabaseLayer().DeleteTimeReport(Guid.Parse(form["ReportId"]));
return RedirectToAction("Summary", "Reports");
}
Note that this will do a client-side redirect, so to say - this will do a response with code 302 and new URL /Reports/Summary. This is usually a desired behavior though.
The exception you're getting is because your code assumes the item you're deleting will exist.
Change
return db.TimeReports.Where(x => x.TimeReportID == timeReportId).Single();
To
return db.TimeReports.Where(x => x.TimeReportID == timeReportId).SingleOrDefault();
Which will return null if your Where clause returns 0 items.
Then wherever in your code you're calling GetTimeReport() you need to check for and handle null.
I gave a Devexpress GridView which represent addresses. Two cascading combobox (Governorate- Area). When the user choose a Governorate the area combo will filtered according to the Governorate chased. When the user doesn't know the corresponding Governorate for the area, he only start by choosing the area and the governorate combobox will fill with the right governorate.
In index.chtml
<script type="text/javascript">
function governorateCombo_SelectedIndexChanged(s, e) {
areaCode.PerformCallback();
}
function AreaCombo_BeginCallback(s, e) {
e.customArgs['governorateCode'] = governorateCode.GetValue();
}
function areaCombo_SelectedIndexChanged(s, e) {
governorateCode.PerformCallback();
}
function GovernorateCombo_BeginCallback(s, e) {
e.customArgs['areaCode'] = areaCode.GetValue();
}
function GovernorateCombo_EndCallback(s, e) {
benGeoGridView.Refresh();
var bla = '#Session["governorateCode"]';
var item = s.FindItemByValue(bla);
s.SetSelectedItem(item);
}
ComboboxGovernoratePartial.chtml
#Html.DevExpress().ComboBox(settings =>
{
settings.CallbackRouteValues = new { Controller = "benFile", Action = "ComboBoxGovernoratePartial" };
settings.Name = "governorateCode";
settings.Properties.TextField = "governorateName1";
settings.Properties.ValueField = "governorateCode";
settings.Properties.ValueType = typeof(string);
settings.Width = 220;
settings.Properties.EnableSynchronization = DefaultBoolean.False;
settings.Properties.IncrementalFilteringMode = IncrementalFilteringMode.StartsWith;
if (Thread.CurrentThread.CurrentCulture.Name.Substring(0, 2) == "ar")
{
settings.RightToLeft = DefaultBoolean.True;
}
settings.Properties.ClientSideEvents.BeginCallback = "GovernorateCombo_BeginCallback";
settings.Properties.ClientSideEvents.SelectedIndexChanged = "governorateCombo_SelectedIndexChanged";
settings.Properties.ClientSideEvents.EndCallback = "GovernorateCombo_EndCallback";
}).BindList(Model).Bind(ViewData["governorateCode"]).GetHtml()
In controller:
public ActionResult ComboBoxGovernoratePartial()
{
string areaCode = (Request.Params["areaCode"] != null) ? Request.Params["areaCode"] : "-1";
List<governorateName> governorateNames = new List<governorateName>();
governorateMaster governorateMaster = new governorateMaster();
if (areaCode != null)
{
Session["governorateCode"] = Masters.areaMasters.First(a => a.areaCode == areaCode).governorateCode; ;
ViewData["governorateCode"] = Masters.areaMasters.First(a => a.areaCode == areaCode).governorateCode;
governorateNames = Masters.governorateNames.Where(a => a.langCode.ToLower() == Thread.CurrentThread.CurrentCulture.Name.Substring(0, 2)).ToList();
}
return PartialView(governorateNames.ToList());
}
When the user choose the area, (in js) I call perform call back for the governorate combobox that the controller pick up the right governorate to populate in the governorate combobox. The problem is that when I send the governorate code in a ViewData it is always null. In a Session varible, the value of it is the one at page load not the updated one in the controller.
Any suggestion ?
Sorry for your time guys
For that, you can try:
TempData["yourVar"]
I have an ActionResult that returns a View with a grid that show notes from a database. On the same page there is a button to call CreateNote, which returns a PartialView where I can add new notes. This all works, but after adding the new note I want the view to go back to the TabNotes showing the grid.
I tried using
return Redirect(HttpContext.Request.UrlReferrer.AbsoluteUri);
but this goes to the wrong page. So instead I want to return the TabNotes ActionResult. Is this possible?
public ActionResult CreateNote(
[ModelBinder(typeof(Models.JsonModelBinder))]
NoteModel Model, string cmd, long? itemId, string modelEntity)
{
if (cmd == "Save")
{
Model.meta.message = "Note saved";
//standard user = 1, needs to be changed to variable
test.Database.User User = UserRepository.GetUser(1);
Entity entity = NotesRepository.GetEntity("Phrase");
NotesRepository.StoreNote(Model.subject, Model.text, User, entity, itemId);
return Redirect(HttpContext.Request.UrlReferrer.AbsoluteUri);
}
Model.meta.modelname = "CreateNote";
Model.meta.JsViewModelType = "EditNoteModel";
Model.meta.PostAction = Url.Action("CreateNote", new { cmd = "Save", itemId = itemId});
return PartialView("CreateNotePartial",Model);
}
'
public ActionResult TabNotes([ModelBinder(typeof(Models.JsonModelBinder))]
TabNotesModel Model, string cmd)
{
Entity entity = NotesRepository.GetEntity(Model.meta.entity);
if (Model.meta.id.HasValue)
{
Model.meta.modelname = "TN" + Model.meta.entity + Model.meta.id.Value.ToString();
Dictionary<string, object> defaultValues = new Dictionary<string, object>();
defaultValues.Add("Entity", entity.EntityId);
defaultValues.Add("ItemId", Model.meta.id.Value);
Entity noteEntity = NotesRepository.GetEntity("Note");
var grid = UI.GetEntityFlexiGrid(noteEntity, true, true, true, true, defaultValues);
grid.buttons.Clear();
grid.title = "";
Model.Grid = grid;
Model.Grid.url = Url.Action("TabNoteData", new { id = Model.meta.entity, itemId = Model.meta.id.Value});
}
return View("TabNotes", Model);
}
You should redirect to the action:
return RedirectToAction("TabNotes");