TextBoxFor not displaying value (MVC4) - asp.net-mvc-4

I got the following controls in my view:
<div class="editor-label">
#Html.LabelFor(model => model.Number)
</div>
<div class="editor-field">
#Html.HiddenFor(model => model.Number)
#Html.TextBoxFor(model => model.Number, new { disabled = "disabled" })
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ProjectID)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.Project.ID, Model.ProjectList, "Select", new { onchange = "SelectedIndexChanged()" })
</div>
I submit the form when the dropdownlist value change to generate the Number field of the model, then the view is reloaded. When the is no HiddenFor control, the Number of the model is displayed properly in the TextBoxFor. When I add a HiddenFor control, the Number field is not displayed although Model.Number is not null.
What is the reason of this?
The reason why I want a HiddenFor with the Number value is that when I submit the form for saving, model.Number equals null. I thought by putting the value in a HiddenFor I would have access to it...
Edit: Controller method
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateOpportunity(CreateEditOpportunityModel model)
{
// if the submit is made by the ddl
if (model.SubmitValue.Equals("ChangeProject"))
{
Project parentProject = pCtx.Projects.Find(model.Project.ID);
if (parentProject != null)
{
// Generate the "Number field"
Region projectRegion = rCtx.Regions.Find(parentProject.RegionID);
int numOpportunity = oCtx.Opportunitites.Count(o => o.ProjectID == parentProject.ID);
numOpportunity++;
string oppNumber = numOpportunity < 10 ? "0" + numOpportunity : numOpportunity.ToString();
model.Number = projectRegion.Name + "-" + parentProject.ID + "-" + oppNumber;
}
// Repopulate the ddl
model.ProjectList = new SelectList(pCtx.Projects, "ID", "ID");
return View(model);
}
// if submit is made by the save button
else if (model.SubmitValue.Equals("CreateOpportunity"))
{
if (ModelState.IsValid)
{
Opportunity opportunity = new Opportunity();
opportunity.ID = model.ID;
opportunity.Number = model.Number;
opportunity.ActivationDate = model.ActivationDate;
opportunity.Assignee = model.Assignee;
opportunity.Comments = model.Comments;
opportunity.CreationDate = DateTime.Now;
opportunity.LicenseFilePath = model.LicenseFilePath;
opportunity.LicenseRequestFilePath = model.LicenseRequestFilePath;
opportunity.OkPermanentStatus = model.OkPermanentStatus;
opportunity.PaidStatus = model.PaidStatus;
opportunity.PartNumber = model.PartNumber;
opportunity.Project = pCtx.Projects.Find(model.Project.ID);
//tell EF that Project already exists in Company table
oCtx.Entry(opportunity.Project).State = EntityState.Modified;
// Saves project
oCtx.Opportunitites.Add(opportunity);
oCtx.SaveChanges();
return RedirectToAction("Index");
}
model.ProjectList = new SelectList(pCtx.Projects, "ID", "ID");
return View(model);
}
model.ProjectList = new SelectList(pCtx.Projects, "ID", "ID");
return View(model);
}
This part of the code works fine, I'm just putting it here to clarify things.

Related

Modal Pop-Up Not Closing Properly After Form Submission

This is a follow-up to the following post:
Modal Pop-Up Displaying Incorrectly When ModelState.IsValid = false Redirect
My Pop-Up validates correctly but after it process the form data it is not getting closed. Once the data gets loaded in the db, I run the following:
TempData["ID"] = status.IssueID;
return RedirectToAction("edit");
Since the Modal doesn't close, the view data gets populated in the modal and not the window.
If I try to use return View("edit"); the underlying page fails because there is no model data on the page.
Here is the current code that I implemented from the post referenced above:
<script>
$('body').on('click', '.modal-link', function () {
var actionUrl = $(this).attr('href');
$.get(actionUrl).done(function (data) {
$('body').find('.modal-content').html(data);
});
$(this).attr('data-target', '#modal-container');
$(this).attr('data-toggle', 'modal');
});
$('body').on('click', '.relative', function (e) {
e.preventDefault();
var form = $(this).parents('.modal').find('form');
var actionUrl = form.attr('action');
var dataToSend = form.serialize();
$.post(actionUrl, dataToSend).done(function (data) {
$('body').find('.modal-content').html(data);
});
})
$('body').on('click', '.close', function () {
$('body').find('#modal-container').modal('hide');
});
$('#CancelModal').on('click', function () {
return false;
});
$("form").submit(function () {
if ($('form').valid()) {
$("input").removeAttr("disabled");
}
});
</script>
Here is the code that I run to open the modal:
<div id="modal-container" class="modal fade" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
</div>
</div>
</div>
Add New Status
And here are the actions when I submit data from the modal:
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult CreateEdit(StatusViewModel model)
{
if (ModelState.IsValid)
{
StatusModel status = new StatusModel();
status.IssueID = model.IssueID;
status.StatusDate = DateTime.Today;
status.Status = model.Status;
status.ColorCode = model.ColorCode;
status.NextStep = model.NextStep;
if (model.addedit == "edit")
{
status.UpdatedByNTID = AppHttpContext.Current.Session.GetString("userntid").ToString();
string done = _adoSqlService.UpdateStatus(status);
}
else
{
status.EnteredByNTID = AppHttpContext.Current.Session.GetString("userntid").ToString();
string done = _adoSqlService.InsertStatus(status);
}
TempData["ID"] = status.IssueID;
return RedirectToAction("edit");
}
else
{
return PartialView("_CreateEdit", model);
}
}
Before I implemented the Javascript code as identified in the link, the modal form closed properly but I couldn't validate. After implementation, the modal form validates but the modal receives the redirect instead of closing. What am I doing wrong
the Modal doesn't close, the view data gets populated in the modal and not the window.
It's the expected result, Ajax render the result of redirection to the modal. You should do the redirection in the done function.
Modify the CreateEdit method:
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult CreateEdit(StatusViewModel model)
{
if (ModelState.IsValid)
{
StatusModel status = new StatusModel();
status.IssueID = model.IssueID;
status.StatusDate = DateTime.Today;
status.Status = model.Status;
status.ColorCode = model.ColorCode;
status.NextStep = model.NextStep;
if (model.addedit == "edit")
{
status.UpdatedByNTID = AppHttpContext.Current.Session.GetString("userntid").ToString();
string done = _adoSqlService.UpdateStatus(status);
}
else
{
status.EnteredByNTID = AppHttpContext.Current.Session.GetString("userntid").ToString();
string done = _adoSqlService.InsertStatus(status);
}
TempData["ID"] = status.IssueID;
}
return PartialView("_CreateEdit", model);
}
Add a hidden input in the partial view to mark if the returned model has passed the validation.
<input name="IsValid" type="hidden" value="#ViewData.ModelState.IsValid.ToString()" />
Then determine whether to redirect in the script:
$('body').on('click', '.relative', function (e) {
e.preventDefault();
var form = $(this).parents('.modal').find('form');
var actionUrl = form.attr('action');
var dataToSend = form.serialize();
$.post(actionUrl, dataToSend).done(function (data) {
$('body').find('.modal-content').html(data);
var isValid = $('body').find('[name="IsValid"]').val() == 'True';
if (isValid) {
$('body').find('#modal-container').modal('hide');
window.location.href = "/Issue/Edit";
}
});
})
Result:

Controller is not returning Viewbag value to the View

I have a controller named CallAllocation, and a View CallAllocation.
At first when the page loads only two dropdown appears with a submit button. On submission, page gets filled with rest of the details based on the selection from the two dropdowns. To achieve that I have made the following code:
Please focus on ViewBag.IsValid condition
My Controller be like
[HttpGet]
public ActionResult CallAllocation()
{
ViewBag.UserName = User.Identity.Name.ToString();
try
{
var NatureList = (from a in dataContext.CallNatures
select a);
Allocation Allocate = new Allocation();
Allocate.CallNaturelist = NatureList.ToList();
ViewData["SelectedTicket"] = 0;
Allocate.CallTicketList = null;
ViewBag.IsValid = "";
return View(Allocate);
}
catch (Exception ex)
{
TempData["ErrMsg"] = ex.Message;
return RedirectToAction("ShowError");
}
}
My View be like
#using (Html.BeginForm("CallAllocation", "Home", FormMethod.Post, new { id = "FrmCallAllocate"}))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
#Html.Raw(ViewBag.ErrMsg)
<div class="row ">
<div class="col-sm-12">
#if (ViewBag.IsVaild == "True")
{
#Html.DropDownListFor(m => m.SelectedCallNature, new SelectList(Model.CallNaturelist, "CallNatureID", "Description"),
"Select Nature", new { style = "width:250px", #class = "dropdown1", #readonly = "readonly;" })
#Html.DropDownList("CallTicket", new SelectList(string.Empty, "CallTicketNumber", "CallTicketNumber"), "Select Call Ticket",
new { style = "width:250px", #class = "dropdown1" , #readonly = "readonly;" })
<input type="submit" value="Get Ticket" style="background-color:#C5C5C5"/>
}
else
{
#Html.DropDownListFor(m => m.SelectedCallNature, new SelectList(Model.CallNaturelist, "CallNatureID", "Description"),
"Select Nature", new { style = "width:250px", #class = "dropdown1" })
#Html.DropDownList("CallTicket", new SelectList(string.Empty, "CallTicketNumber", "CallTicketNumber"), "Select Call Ticket",
new { style = "width:250px", #class = "dropdown1"})
<input type="submit" value="Get Ticket" style="background-color:#C5C5C5"/>
}
</div>
</div>
}
As you can see Controller sends ViewBag value "", and it should enter else condition of the View. But it is bypassing both the conditions.
Please help me understand why the controller is unable to send Viewbag value to the view. I have made similar cases but it's working in rest.
I have tried clearing the cache too.
Please note that my View is a strongly-typed View.

Dropdowns not rendered when override object.cshtml MVC4

My actual problem was mentioned here.
Hide property of model in dynamic view
To solve the problem, I have overrided object.cshtml as mentioned in the answer.
However, when I did this, the dropdowns that I am rendering using UIHints are not working.
In place of dropdown, just False, False False (the no.of Falses are equal to number of list items I have in my viewdata) are displayed.
I am not sure what is happening here, can somebody advise what is going on?
in my controller:
ViewData["PartyRoleTypeId"] = (IEnumerable<SelectListItem>)PartyRoleTypeRepo.All()
.ToList()
.Select(p => new SelectListItem { Value = p.PartyRoleTypeId.ToString(), Text = p.Caption, Selected = p.PartyRoleTypeId == obj.PartyRoleTypeId });
ViewData["PartyId"] = (IEnumerable<SelectListItem>)PartyRepo.All()
.ToList()
.Select(p => new SelectListItem { Value = p.PartyId.ToString(), Text = p.Organization.Caption, Selected = p.PartyId == obj.PartyId });
My dropdown edit template in shared/editortemplates/DropDownList.cshtml
#{
var fieldName = ViewData.ModelMetadata.PropertyName;
}
#Html.DropDownList("",(IEnumerable<SelectListItem>)ViewData[fieldName], "Choose..." , new { #class ="combo"})
object.cshtml
#functions
{
bool ShouldShow (ModelMetadata metadata)
{
return metadata.ShowForEdit
&& metadata.ModelType != typeof(System.Data.EntityState)
&& !metadata.IsComplexType
&& !ViewData.TemplateInfo.Visited(metadata);
}
}
#if (ViewData.TemplateInfo.TemplateDepth > 1)
{
if (Model == null)
{
#ViewData.ModelMetadata.NullDisplayText
}
else
{
#ViewData.ModelMetadata.SimpleDisplayText
}
}
else
{
//ViewData.Clear();
foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => ShouldShow(pm)))
{
if (prop.HideSurroundingHtml)
{
#Html.Editor(prop.PropertyName)
}
else if (prop.DisplayName == "Id")
{
<div></div>
}
else if (!string.IsNullOrEmpty(Html.Label(prop.PropertyName).ToHtmlString()))
{
<div class="editor-label">#Html.Label(prop.PropertyName)</div>
}
<div class="editor-field">#Html.Editor(prop.PropertyName) #Html.ValidationMessage(prop.PropertyName, "")</div>
}
}
There is some problem with keeping my dropdown values in ViewData or ViewBag.
When I use these, for prartyroletypeid it is not recognizing UIHint dropdownlist.cshtml. It is still referring to object.cshtml.
Instead I kept the dropdown data in TempData and everything is working fine.
But not sure, if I can use TempData in this context.
Any ideas???

Export to CSV file centrally in Asp.Net MVC

I am doing Export to csv functionality in my MVC project. Currently if i write code on each page it works properly. but i want to avoid duplication of code doing export functionality centrally.
Here is my controller code
public ActionResult Export(string filterBy)
{
GridState gs = new GridState();
gs.Filter = filterBy;
gs.Page = 1;
gs.Size = int.MaxValue;
IEnumerable cities = City.GetAll().AsEnumerable().AsQueryable().ToGridModel(gs).Data;
MemoryStream output = new MemoryStream();
StreamWriter writer = new StreamWriter(output, Encoding.UTF8);
writer.Write("Country Name,");
writer.Write("State Name,");
writer.Write("City Name,");
writer.Write("City STD Code,");
writer.Write("Is Display");
writer.WriteLine();
foreach (CityViewModel city in cities)
{
writer.Write(city.CountryName);
writer.Write(",");
writer.Write("\"");
writer.Write(city.StateName);
writer.Write("\"");
writer.Write(",");
writer.Write("\"");
writer.Write(city.City.Name);
writer.Write("\"");
writer.Write(",");
writer.Write(city.City.STDCode);
writer.Write("\"");
writer.Write(",");
writer.Write(city.City.IsDisplay);
writer.WriteLine();
}
writer.Flush();
output.Position = 0;
return File(output, "text/comma-separated-values", "city.csv");
}
This is my View:
#model Telerik.Web.Mvc.GridModel<QuexstERP.BusinessCore.BusinessEntities.SysAdmin.CityViewModel>
#using Telerik.Web.Mvc.UI
#{
ViewBag.Title = "City List";
}
#(Html.Telerik().Grid(Model.Data)
.Name("Grid")
.DataKeys(keys => keys.Add(c => c.City.Id))
.ToolBar(commands => commands.Insert().ButtonType(GridButtonType.Image).ImageHtmlAttributes(new { style = "margin-left:0", title = "Add" }))
.ToolBar(commands => commands
.Custom()
.HtmlAttributes(new { id = "TestFilter", onclick = "command_onClick(this)" })
.Text("Export to csv")
.Action("Export", "City", new { filterBy = "~" }))
.DataBinding(dataBinding =>
dataBinding.Server()
.Select("Select", "City", new { GridButtonType.Text })
.Insert("Create", "City", new { GridButtonType.Text })
.Update("Save", "City", new { GridButtonType.Text })
.Delete("Delete", "City", new { GridButtonType.Text }))
.Columns(columns =>
{
columns.Command(commands =>
{
commands.Custom("Edit").Action("Edit", "City").ImageHtmlAttributes(new { #class = "t-edit" }).ButtonType(GridButtonType.Image).HtmlAttributes(new { title = "Edit", #class = "RightAlign" });
}).Width(40).Title("Edit").Visible(OperationHelper.EditOperation);
columns.Command(commands =>
{
commands.Delete().ButtonType(GridButtonType.Image).HtmlAttributes(new { title = "Delete", #class = "RightAlign" });
}).Width(40).Title("Delete").Visible(OperationHelper.DeleteOperation);
columns.Bound(p => p.CountryName).Width(200).Title("Country");
columns.Bound(p => p.StateName).Width(200).Title("State");
columns.Bound(p => p.City.Name).Width(310).Title("City");
columns.Bound(p => p.City.STDCode).Width(200).Title("STD Code");
columns.Bound(p => p.City.IsDisplay).Width(110).Title("IsDisplay");
})
.Pageable()
.Scrollable()
.Sortable()
.Filterable()
.Resizable(command => command.Columns(true))
)
#section HeadContent {
<script type="text/javascript">
function command_onClick(e) {
var grid = $('#Grid').data('tGrid');
var $cmd = $('#TestFilter');
// Get its 'href' attribute - the URL where it would navigate to
var href = $cmd.attr('href');
// Update the 'filter' parameter with the grids' current filtering state
href = href.replace(/filterBy=(.*)/, 'filterBy=' + (grid.filterBy || '~'));
// Update the 'order' parameter with the grids' current ordering state
href = href.replace(/orderBy=([^&]*)/, 'orderBy=' + (grid.orderBy || '~'));
// Update the 'page' parameter with the grids' current page
href = href.replace(/page=([^&]*)/, 'page=' + grid.currentPage);
// Update the 'href' attribute
$cmd.attr('href', href);
}
</script>
}
I want to do Export to CSV centrally. as many of the form like state, country and country in my project have the exporting functionality. is it possible to write one generic class and pass parameter to it. and export to csv is done centrally???
We achieved something similar to this by binding datasources to a GridView within a controller method e.g.
var data = GetSomeData();
var grid = new GridView { DataSource = data };
grid.DataBind();
Response.ClearContent();
Response.AddHeader("content-disposition", "attachment; filename=MyExcel.xls");
Response.ContentType = "application/vnd.ms-excel";
var sw = new StringWriter();
var htw = new HtmlTextWriter(sw);
grid.RenderControl(htw);
Response.Write(sw.ToString());
Response.End();
This way you can just set the relevant datasource on the GridView and return a dump of the grid data in the output stream. With a bit of refactoring we were able to make this generic and it is now used by all of our UI grids for exporting to Excel/CSV.
Just for the reference. Don't bind data to the grid and then export it to excel. It will give you
the file you are trying to open is in a different format than
specified by the file extension
Error when you try to open Excel.
I have done this solution for above problem
public static void ExportToExcel(IEnumerable<dynamic> data, string sheetName)
{
XLWorkbook wb = new XLWorkbook();
var ws = wb.Worksheets.Add(sheetName);
ws.Cell(2, 1).InsertTable(data);
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
HttpContext.Current.Response.AddHeader("content-disposition", String.Format(#"attachment;filename={0}.xlsx",sheetName.Replace(" ","_")));
using (MemoryStream memoryStream = new MemoryStream())
{
wb.SaveAs(memoryStream);
memoryStream.WriteTo(HttpContext.Current.Response.OutputStream);
memoryStream.Close();
}
HttpContext.Current.Response.End();
}
It get data dynamically. use ClosedXml so no error and the Export to Excel functionality is central in application
Hope this will help someone. :)

Html.CheckBox not being set [asp.net mvc 4]

I am having a bit of a headache with a thing (I know something like has been asked before, but I'm pretty sure it's not quite the same thing).
To the point:
I have a View with a Telerik grid. On that grid I show some stuff from the model that I pass to the View BUT I want in the final column to put a CheckBox that is checked/unchecked based on some things in the Controller (the checks have nothing to do with the model that is being passed). In my ActionResult function that takes care of the View I store some Boolean values in the ViewData, and then I set the isChecked value in the CheckBox based on the values stored in the ViewData.
The code for the ActionResult is as follows:
[SecureThis(Roles = "User")]
public ActionResult Index()
{
//get bucket ids
var buckets = db.Buckets.ToList();
int i=1;
string cb = "checkbox" + i.ToString();
foreach (Bucket b in buckets)
{
var payByInvoice = db.PaymentOptions.Where(p => p.BucketId == b.Id).Select(p => p.CanPayByInvoice).SingleOrDefault();
if (payByInvoice == (int)PayByInvoiceState.Accepted)
ViewData["checkbox" + i.ToString()] = true;
else ViewData["checkbox" + i.ToString()] = false;
i++;
cb = "checkbox" + i.ToString();
}
return View(db.Buckets);
}
And the grid that should show all the stuff is this:
#{
int i=1;
string cb = "checkbox" + i.ToString();
}
#(Html.Telerik().Grid(Model)
.Name("BucketsGrid")
.DataKeys(keys => keys.Add(bucket => bucket.Id))
.Columns(
columns =>
{
columns.Template(model => ViewData[model.Id.ToString()])
.HeaderTemplate(
#<b>#Strings.Title_Customer</b>
);
columns.Bound(model => model.CreditFacility);
columns.Bound(model => model.Minimum);
columns.Bound(model => model.RefillLevel);
columns.Bound(model => model.NotificationEmail);
columns.Bound(model => model.NotificationSms);
columns.Template(model => Html.ActionLink(Strings.Edit, "Edit", new { id = model.Id }));
columns.Template(model => Html.ActionLink(Strings.NotificationOptions, "Bucket", "NotificationOptions", new { id = model.Id }, null));
columns.Template(model => Html.ActionLink("Refill", "Refill", "Payment", new { id = model.Id }, null));
columns.Template(model => Html.ActionLink(Strings.Details, "Details", new { id = model.Id }));
columns.Template(model => Html.ActionLink(Strings.Delete, "Delete", new { id = model.Id }));
columns.Template(model => Html.CheckBox("invoice", (Boolean)ViewData[#cb])).HeaderTemplate("Invoice Option");
#i++;
#cb = "checkbox" + i.ToString();
}
)
.Pageable(paging =>
paging.Enabled(true)
.PageSize(UserSettings.GridPageSize)
.Style(GridPagerStyles.NextPrevious)
.Position(GridPagerPosition.Bottom)
)
.Sortable()
.Scrollable()
.Resizable(resize=> resize.Columns(true))
)
The problem with this whole thing is that the checkboxes remain unchecked, no matter the data stored in the ViewData. I went with the debugger and the values are se accordingly in the ViewData, but for some reason (that I cannot yet tell) the checkboxes still remain unchcked.
Any ideas on this matter would be much appreciated.
I have found out the problem of all this. As expected, it was my own doing (or so to say). The problem was that I incremented the #i variable inside the Telerik grid declaration, thinking that it would happen for all the rows in the grid, but that thing is only triggered once. Hence, the ViewData[#cb] value would always have the 2nd value set in the Controller (which in my case was false) and all the checkboxes would then be unchecked.
The fix:
I used the ViewBag and set it up with a Dictionary<Guid, bool> to hold my values, and iterate through it using the model.Id property. For anyone who might be interested I'll post the code below.
Controller:
ViewBag.Dict = new Dictionary<Guid, bool>();
Dictionary<Guid, bool> dict = new Dictionary<Guid, bool>();
foreach (Bucket b in buckets)
{
var payByInvoice = db.PaymentOptions.Where(p => p.BucketId == b.Id).Select(p => p.CanPayByInvoice).SingleOrDefault();
if (payByInvoice != (int)PayByInvoiceState.Accepted)
{
dict.Add(b.Id, false);
}
if (payByInvoice == (int)PayByInvoiceState.Accepted)
{
dict.Add(b.Id, true);
}
}
ViewBag.Dict = dict;
View:
columns.Template(model => Html.CheckBox("invoice", (bool)ViewBag.Dict[model.Id])).HeaderTemplate("Invoice option");