I am making a page that stores clients. Clients can have domains and contacts and jobs.
Each contact/domain/job has edit/delete functionality.
I am using MVC 4 ASP.NET c#
each time you wish to edit/delete it launches a modal form.
The delete view for contact and domain is exactly the same except for the fields that it displays. The domain delete function does not fire anything when it is in partial view. But it succeeds when it is navigated to in the url as a regular view. the contact delete works fine in the partial view.
#model STClient.Models.Domain
#{
ViewBag.Title = "DeleteDomain";
}
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"></script>
#using (Html.BeginForm("DeleteDomain", "Client", FormMethod.Post)) {
<div class="modal-header">
<h2>Are you sure you want to delete?</h2>
</div>
<div class="modal-body">
<fieldset>
<div class="display-label">
<h3>
#Html.HiddenFor(model => model.server.ID)
#Html.HiddenFor(model => model.ID)
#Html.DisplayNameFor(model => model.Name):
#Html.DisplayFor(model => model.Name)
</h3>
</div>
<div class="display-label">
<h5>
#Html.DisplayNameFor(model => model.Registrar):
#Html.DisplayFor(model => model.Registrar)
</h5>
</div>
<div class="display-label">
<h5>
#Html.DisplayNameFor(model => model.PrimaryDNS):
#Html.DisplayFor(model => model.PrimaryDNS)
</h5>
</div>
<div class ="display-label">
<h5>
#Html.DisplayNameFor(model => model.SecondaryDNS):
#Html.DisplayFor(model => model.SecondaryDNS)
</h5>
</div>
</fieldset>
</div>
<div class="modal-footer">
<a class="btn" href="">Cancel</a>
<input class="btn btn-danger" type ="submit" value="Delete" />
</div>
}
this is on the details page where the delete link is for the domain.
<div class="modal fade" id="deleteDomain-modal"></div>
<script type="text/javascript">
$(function () {
$(".deleteDomain").click(function () {
$.ajax({
url: "/Client/DeleteDomain",
type: "GET",
data: {id: $(this).attr('id')},
dataType: "html",
success: function(e)
{
$("#deleteDomain-modal").html(e);
}
});
$("#deleteDomain-modal").modal();
});
});
</script>
And finally in the Client Controller
public ActionResult DeleteDomain(int id)
{
Domain domain = db.Domains.Find(id);
if (domain == null)
{
HttpNotFound();
}
return PartialView(domain);
}
[HttpPost, ActionName("DeleteDomain")]
public ActionResult DeleteDomainConfirmed(int id)
{
Domain domain = db.Domains.Find(id);
Server server = db.Servers.Find(id);
db.Domains.Remove(domain);
db.SaveChanges();
db.Servers.Remove(server);
db.SaveChanges();
LogDeleteDomain(domain, server);
return RedirectToAction("Index");
}
I think I had a similar problem. The reason was that parameter value was send as string and not as integer. I had to cast the value. So in your script code you may try to change the line:
data: {id: $(this).attr('id')},
to:
data: {id: parseInt($(this).attr('id'))},
That solved my problem.
Related
I am really unsure how to do approach modal dialogs in ASP.NET MVC:
The situation is as follows: In my home/index action method, I check if the user has already accepted the terms and conditions. If not, I want to show a dialog to prompt the user for a confirmation.
Now I am really unsure how to approach this in MVC:
The possibilities I see:
Store a TaCConfirmNeeded property in ViewBag, in my view notice that the viewbag contains this token, display a jquery modal dialog with a form to confirm the terms and cond., and call account/confirmTA from this form.
Create a View in my shared folder, that uses my common layout, and is styled like a modal dialog, with a form which sends to account/confirmTA.
Is there a better/easier possibility?
This is how I implement a Modal Pop-Up in MVC. Hope it can help you.
Create a partial view (example):
#model CodeFirst.Models.FriendsInfo
<div>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">FriendsInfo</h4>
</div>
<hr />
<dl class="dl-horizontal">
<dt>
#Html.DisplayNameFor(model => model.Name)
</dt>
<dd>
#Html.DisplayFor(model => model.Name)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Mobile)
</dt>
<dd>
#Html.DisplayFor(model => model.Mobile)
</dd>
<dt>
#Html.DisplayNameFor(model => model.Address)
</dt>
<dd>
#Html.DisplayFor(model => model.Address)
</dd>
</dl>
The controller it's gonna look like:
public ActionResult Details(int Id)
{
FriendsInfo frnds = new FriendsInfo();
frnds = db.FriendsInfo.Find(Id);
return PartialView("_Details",frnds);
}
Later put this on your _Layout:
<div id='myModal' class='modal'>
<div class="modal-dialog">
<div class="modal-content">
<div id='myModalContent'></div>
</div>
</div>
</div>
And your gonna need this script with a little jQuery to call it with AJAX from your view:
<script>
var PostBackURL = '/Home/Details';
$(function () {
// Use your logic, to call this function and replace the parameters like the User.ID
debugger;
var id = User.Id;
var options = { "backdrop": "static", keyboard: true };
$.ajax({
type: "GET",
url: PostBackURL ,
contentType: "application/json; charset=utf-8",
data: { "Id": id },
datatype: "json",
success: function (data) {
debugger;
$('#myModalContent').html(data);
$('#myModal').modal(options);
$('#myModal').modal('show');
},
error: function () {
alert("Dynamic content load failed.");
}
});
});
//$("#closebtn").on('click',function(){
// $('#myModal').modal('hide');
$("#closbtn").click(function () {
$('#myModal').modal('hide');
});
</script>
I am buidling a mvc web application with entity framework.
Error:
An exception of type 'System.ObjectDisposedException' occurred in
EntityFramework.dll but was not handled in user code
Additional information: The ObjectContext instance has been disposed
and can no longer be used for operations that require a connection.
This is the entity framework part:
Like you see I already include "Alineas" and do .ToList()
public IList<Kop> Handle(RetrieveKoppenForDocumentQuery query)
{
using (var db = new BmDataContext())
{
var koppen = db.Kop.Where(s => s.Document.Id == query.Id)
.Include(s => s.TegelAfbeelding)
.Include(s => s.CollageAfbeeldingen)
.Include(s => s.FinancieleAfbeeldingen)
.Include(s => s.Alineas)
.ToList();
return _orderKoppenByIndex(koppen);
}
}
This is the view KopListItems.cshtml:
#using PGE.Bestuursmonitor.Contracts.DataTypes
#model IList<Kop>
#* Helper for recursively rendering koppen*#
#helper SortableItem(Kop kop)
{
<div class="sortable-item" data-kopid="#kop.Id">
<div class="row">
<div class="col-md-7 title-column">
<i class="fa fa-arrows"></i> #kop.Titel
</div>
<div class="col-md-5">
<div class="col-md-3">
<span>
#kop.KopType
</span>
</div>
<div class="col-md-3">
<span>
#kop.Status
</span>
</div>
<div class="col-md-6">
<span class="pull-right">
#if (#kop.Alineas != null) // on this line I receive the exception
{
// here I would like to do some logic
}
</span>
</div>
</div>
</div>
<div class="sortable-container">
#foreach (var subKop in kop.Koppen)
{
#SortableItem(subKop);
}
</div>
</div>
}
#* Recursively render all kop items *#
<div id="koppen_sortable" class="sortable-container">
#foreach (Kop kop in Model)
{
#SortableItem(kop);
}
</div>
This is the view KoppenList.cshtml:
#model PGE.Bestuursmonitor.ViewModels.Koppen.IKoppenListViewModel
<h1>#Model.DocumentTitel</h1>
#* Render kop list header *#
<div id="koppen_sortable_header">
<div class="row">
<div class="col-md-7"><strong>Titel</strong></div>
<div class="col-md-5">
<div class="col-md-3">
<strong>Type</strong>
</div>
<div class="col-md-3">
<strong>Status</strong>
</div>
<div class="col-md-6">
<span class="pull-right">
<button type="button" id="btn_add_sub" class="btn btn-success" title="Kop aanmaken" role="button" onclick="BM.Koppen.LoadAddKopView(null);">
<i class="fa fa-plus fa-lg"></i> Kop aanmaken
</button>
</span>
</div>
</div>
</div>
</div>
<div id="koppen_sortable_body">
#{ Html.RenderPartial("~/Views/Koppen/KopListItems.cshtml", #Model.Koppen); }
</div>
#* Store document id in html DOM, so javascript can reach it from multiple places *#
<input type="hidden" id="document_id" value="#Model.DocumentId" />
Action in controller:
[HttpGet]
public ActionResult KoppenList(string id)
{
ViewBag.PageId = id;
Document document = _retrieveStartPcDocumentQueryHandler.Handle(new RetrieveStartPcDocumentQuery());
RetrieveKoppenForDocumentQuery query = new RetrieveKoppenForDocumentQuery
{
Id = document.Id
};
IList<Kop> koppen = _retrieveKoppenForDocumentQueryHandler.Handle(query);
_koppenListViewModel.Koppen = koppen;
_koppenListViewModel.DocumentTitel = document.Titel;
_koppenListViewModel.DocumentId = document.Id;
return View("~/Views/Koppen/KoppenList.cshtml", _koppenListViewModel);
}
Like you see in KopListItems.cshtml there are 2 foreach loops. The outer foreach loop is working fine and can read "Alineas". The inner foreach which shows the sub items gives this strange error. What is going wrong? Im stuck.
This is the solution. You need to get the alineas and content also on sub level:
public IList<Kop> Handle(RetrieveKoppenForDocumentQuery query)
{
using (var db = new BmDataContext())
{
var koppen = db.Kop.Where(s => s.Document.Id == query.Id)
.Include(s => s.TegelAfbeelding)
.Include(s => s.CollageAfbeeldingen)
.Include(s => s.FinancieleAfbeeldingen)
.Include(s => s.Alineas.Select(a => a.Content))
.Include(s => s.Koppen.Select(k => k.Alineas.Select(a => a.Content)))
.Include(s => s.Koppen.Select(k => k.Koppen.Select(x => x.Alineas.Select(a => a.Content))))
.ToList();
return _orderKoppenByIndex(koppen);
}
}
I have a table showing the information of the users, with an edit button for each one.
I want to show a modal form with the details for the user I want to edit, but I don't know how to get the details from the list, and passing them to the modal as a model.
Here is my View:
#model MyApp.Models.User
#{
ViewBag.Title = "Users";
var roles = new List<string> { "Manager", "Admin" };
var userRoles = (List<string>)ViewData["userRoles"];
}
<h2>#ViewBag.Title</h2>
#if (userRoles.Any(u => roles.Contains(u)))
{
using (Html.BeginForm("Update", "Admin", FormMethod.Post, new { id = "update-form", value = "" }))
{
<div class="modal fade" id="user-editor" >
<div class="modal-header">
<a class="close" data-dismiss="modal"><h3>×</h3></a>
<h3 id="modal-title">Edit User</h3>
</div>
<div class="modal-body">
<div class="form-group">
#Html.Label("Name", new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Name, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.Label("Age", new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Age, new { #class = "form-control" })
</div>
</div>
</div>
<div class="modal-footer">
<a class="btn" data-dismiss="modal">Close</a>
<input type="submit" class="btn btn-primary" value="Save Changes" />
</div>
</div>
}
}
<table class="table-bordered table-hover" id="tbusers">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
#if (userRoles.Any(u => roles.Contains(u)))
{
<th>Edit</th>
}
</tr>
</thead>
<tbody>
#foreach (var u in users)
{
<tr id="#u.Id">
<td>#u.Name</td>
<td>#u.Age</td>
#if (userRoles.Any(u => roles.Contains(u)))
{
<td><a type="button" class="btn edit-btn" href="#user-editor" data-toggle="modal">Edit</a></td>
}
</tr>
}
</tbody>
</table>
I've created a testing sample which will help you understand how can you achieve this.
Index.cshtml which will show a list of employees
#model IEnumerable<MvcApplication1.Models.Employee>
#using MvcApplication1.Models;
<h2>Index</h2>
<table>
#foreach (Employee item in Model)
{
<tr>
<td>#Html.ActionLink(#item.EmployeeName, "Name", new { id = item.ID })</td>
<td>
<button type="button" data-id='#item.ID' class="anchorDetail btn btn-info btn-sm" data-toggle="modal"
data-target="#myModal">
Open Large Modal</button></td>
</tr>
}
</table>
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Details</h4>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
At the same page, reference the following scripts
<script src="~/Scripts/jquery-3.1.1.min.js"></script>
<script src="~/Scripts/bootstrap.min.js"></script>
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
JQuery AJAX call for getting/setting the data of individual employee from ActionMethod at the same page
<script>
$(document).ready(function () {
var TeamDetailPostBackURL = '/Employee/Details';
$(document).on('click', '.anchorDetail', function () {
var $buttonClicked = $(this);
var id = $buttonClicked.attr('data-id');
var options = { "backdrop": "static", keyboard: true };
$.ajax({
type: "GET",
url: TeamDetailPostBackURL,
contentType: "application/json; charset=utf-8",
data: { "Id": id },
datatype: "json",
success: function (data) {
debugger;
$('.modal-body').html(data);
$('#myModal').modal(options);
$('#myModal').modal('show');
},
error: function () {
alert("Dynamic content load failed.");
}
});
});
$("#closbtn").click(function () {
$('#myModal').modal('hide');
});
});
Now Create a class of Employee(because i'm not using EF)
public class Employee
{
public int ID { get; set; }
public string EmployeeName { get; set; }
}
Create controller named Employee and 2 ActionMethods like these:
public ActionResult Index()
{
return View(emp);//sends a List of employees to Index View
}
public ActionResult Details(int Id)
{
return PartialView("Details",
emp.Where(x=>x.ID==Convert.ToInt32(Id)).FirstOrDefault());
}
I'm returning PartialView because I need to load a page within a page.
Details.cshtml
#model MvcApplication1.Models.Employee
<fieldset>
<legend>Employee</legend>
<div class="display-label">
#Html.DisplayNameFor(model => model.ID)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.ID)
</div>
<div class="display-label">
#Html.DisplayNameFor(model => model.EmployeeName)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.EmployeeName)
</div>
</fieldset>
<p>#Html.ActionLink("Back to List", "Index")</p>
When you execute and visit the Index page of Employee, you'll see screen like this:
And the Modal Dialog with results will be shown like this:
Note: You need to add reference of jquery and Bootstrap and you can further design/customize it according to your needs
Hope it helps!
So I have this partial view:
#model QueryQuestionManager.Models.Domain.Answer
<script src="~/Scripts/DynamicList.js"></script>
<div class="editorRow">
#using (Html.BeginCollectionItem("Answers"))
{
<div>
#Html.LabelFor(x => x.AnswerText)
#Html.EditorFor(x => x.AnswerText)
</div>
delete
}
</div>
I want to load this partial view in my main view when someone clicks the link:
#model QueryQuestionManager.Models.Domain.Question
#{
ViewBag.Title = "Create";
}
<script src="~/Scripts/DynamicList.js"></script>
<br />
#using (Html.BeginForm(new { #class = "form", role = "form" }))
{
<div class="form-group">
<div class="editor-label">
#Html.LabelFor(m => m.QuestionText)
</div>
<div class="form-control">
#Html.TextBoxFor(m => m.QuestionText)
#Html.ValidationMessageFor(m => m.QuestionText)
</div>
<div class="editor-label">
#Html.LabelFor(m => m.Category)
</div>
<div class="form-control">
#Html.TextBoxFor(m => m.Category)
#Html.ValidationMessageFor(m => m.Category)
</div>
<div class="editor-label">
#Html.LabelFor(m => m.Answers)
</div>
<br />
<div id="editorRows">
#foreach (var item in Model.Answers)
{
#Html.Partial("EditorRow", item);
}
</div>
#Html.ActionLink("Add another...", "BlankEditorRow", "Question", new { id = "addItem" })
<br />
<input type="submit" value="Save" class="btn btn-success" />
</div>
}
<br />
<div>
#Html.ActionLink("Back to List", "Index", "Home")
</div>
This is the action result from the controller
public ActionResult BlankEditorRow()
{
return PartialView("EditorRow", new Answer());
}
And then I have a javascript file for the dynamic adding and deleting partial views.
$('#addItem').click(function () {
$.ajax({
url: this.href,
cache: false,
success: function (html) {
$('#editorRows').append(html);
}
});
return false;
});
$('a.deleteRow').live('click', function () {
$(this).parents('div.editorRow:first').remove();
return false;
});
But for some reason my partial view doesn't load inside my current view and it opens only the partial view.
Am I forgetting something?
I'm thinking you don't want that action link. I believe your jQuery click handler has the correct approach, but your action link is linking to your new URL (Question/BlankEditorRow) and you don't want that. Rather you just need to fetch this html, and insert it as you do, but WITHOUT navigating the main page to that URL.
Instead of the ActionLink, use an anchor tag and a hidden field.
<a id="addItem" href="#" />
<input type="hidden" id="partialViewAction" value="#Url.Action("BlankEditorRow","ControllerName")"
Now in your ajax call, instead of using the href property of the anchor, use the value of the hidden field.
url: $('#partialViewAction').val()
I try to make user registation form. I have two user types and want to make two JQuery UI tabs with forms. But tab is empty and in java script console error "GET http://localhost/ParcDocs/Admin/Users/AddWorker 500 (Internal Server Error)".
Code of user registration page:
<script type="text/javascript">
$(document).ready(function() {
$("#tabContainer").tabs();
});
</script>
<div id="tabContainer">
<ul>
<li>#Html.ActionLink("Пользователь", "AddUser", "Users", null, null)</li>
<li>#Html.ActionLink("Сотрудник", "AddWorker", "Users", null, null)</li>
</ul>
</div>
PartialView code:
#model ParcDocs.Models.WorkerUser
#using (Html.BeginForm("AddWorker", "Users"))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Пользователь</legend>
<div class="editor-label">
#Html.LabelFor(model => model.UserName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.UserName)
#Html.ValidationMessageFor(model => model.UserName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Password)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.UserName)
#Html.ValidationMessageFor(model => model.Password)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.RoleId, ((IEnumerable<ParcDocs.Models.Role>)ViewBag.PossibleRoles).Select(option => new SelectListItem
{
Text = (option == null ? "None" : option.Name),
Value = option.Id.ToString(),
Selected = (Model != null) && (option.Id == Model.RoleId)
}), "Выберете роль пользователя")
</div>
<p>
<input type="submit" value="Добавить" />
</p>
</fieldset>
}
Controller code:
public ActionResult AddWorker()
{
var model = new WorkerUser();
return PartialView(model);
}
Same behavior this second tab.
You should be returning a PartialViewResult, rather than an ActionResult. Put a breakpoint on public ActionResult AddWorker() and see what exception you get. Paste it here so that we have more information.