Persisting session data to child views MVC 3 - asp.net

So I'm working on an MVC 3 project that pulls from multiple (10) tables from a legacy data source to a Master View with 6 partials. There is one table that has data on every child view, so we decided to store that in session data and then populate the rest of the child views with whatever other data is needed.
When we originally tried to do this, we were getting null reference exceptions to the session data. I've come up with a solution, but it seems very clunky and I don't think it's best practices/introducing unnecessary state.
Relevant code to follow:
This is what we have on the main controller:
public ActionResult PolicyView(string PolicyID)
{
IPolicyHolder phdata = new PolicyHolderData();
Polmast policy = phdata.GetPolicyFromUV(PolicyID);
ViewBag.FullName = policy.FULLNAME;
ViewBag.PolicyID = PolicyID;
Session["polmast"] = policy;
return View("PolicyView");
}
And then in our main view, one of the links to the partial child views:
<div id="Billing">
#{ Html.RenderAction("Billing", Session["polmast"] ); }
</div>
In the child controller:
public ActionResult Billing(object sessiondata)
{
return PartialView("_Billing", sessiondata);
}
And in the child view:
#{var polmast = (Polmast)Session["polmast"];}
**snip**
<table id="premiumsgrid" class="display" border="1"
cellpadding="0" cellspacing="0" width="50%">
<thead>
<tr>
<th>Annual</th>
<th>Semi-Annual</th>
<th>Quarterly</th>
<th>Monthly</th>
</tr>
</thead>
<tbody>
<tr>
<td>#polmast.PAN</td>
<td>#polmast.PSA</td>
<td>#polmast.PQT</td>
<td>#polmast.PMO</td>
</tr>
</tbody>
</table>

I would recommend starting to use models and returning those to your views instead of passing around the session object and casting it within your view. It would make this code much more clean.
This is how I would structure my code:
public ActionResult PolicyView(string PolicyID)
{
IPolicyHolder phdata = new PolicyHolderData();
Polmast policy = phdata.GetPolicyFromUV(PolicyID);
PolicyModel model = new PoliceModel() {
FullName = policy.FULLNAME,
PolicyID = PolicyID
//Populate other properties here.
};
Session["polmast"] = policy;
return View("PolicyView", model);
}
Then I would set up your main view (there's no need to wrap this call in curly braces and you shouldn't need to pass any route values):
<div id="Billing">
#Html.RenderAction("Billing")
</div>
The child controller:
public ActionResult Billing()
{
//Get the data out of session; it should already exist since your parent controller took care of it.
var policyData = (Polmast)Session["polmast"];
PolicyModel model = new PoliceModel() {
FullName = policy.FULLNAME,
PolicyID = PolicyID
//Populate other properties here.
};
return PartialView("_Billing", model);
}
And your child view:
#model Polmast
snip
<table id="premiumsgrid" class="display" border="1"
cellpadding="0" cellspacing="0" width="50%">
<thead>
<tr>
<th>Annual</th>
<th>Semi-Annual</th>
<th>Quarterly</th>
<th>Monthly</th>
</tr>
</thead>
<tbody>
<tr>
<td>#Model.PAN</td>
<td>#Model.PSA</td>
<td>#Model.PQT</td>
<td>#Model.PMO</td>
</tr>
</tbody>
</table>

Related

asp.net event handler for table click is called twice

I have a table with some column in a asp.net mvc core project.
My view file looks like this
<h1>Items</h1>
<div class="panel-body">
<table class="table table-bordered table-responsive table-hover">
<thead>
<tr>
<th>Id</th>
<th>Title</th>
<th>Rating</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Items)
{
<tr onclick="location.href='#(Url.Action("ShowItemDetails", "Item", new {Id = item.FilmId}))'">
<td>#item.Id</td>
<td>#item.Title</td>
<td>#item.Rating</td>
<td>#Html.ActionLink("Edit", "Edit", "Show", new { id = item.Id }) | #Html.ActionLink("Rate this", "RateItem", new { id = item.Id }) </td>
</tr>
}
</tbody>
</table>
</div>
The problem is that when i click on a row, the controller method ShowItemDetails is called twice(!).
I can not see from the code above why this happens. Also, clicking on Edit or Rate this calls first ShowItemDetails and then immediately Edit or RateItem method in controller. Any suggestion how this can be solved?
Clicking on Edit or Rate this calls first ShowItemDetails and then immediately Edit or RateItem method because Edit is under a table row and on tablerow, you have called showitemdetails action.so, when you click on td , it gets first executed row action then td action.that's why it get called twice.
I hope, you want to show details and edit options with data of table and Edit is controller name.
Tweak your table code like below:
<tbody>
#foreach (var item in Model.Items)
{
<tr>
<td>#Html.ActionLink("Show Details","ShowItemDetails","Item",new {Id = item.FilmId})</td>
<td>#item.Id</td>
<td>#item.Title</td>
<td>#item.Rating</td>
<td>#Html.ActionLink("Edit", "Edit", "Show", new { id = item.Id }) | #Html.ActionLink("Rate this", "RateItem", new { id = item.Id }) </td>
</tr>
}
</tbody>
The problem seems to be caused be something i thought was irrelevant
having a null image cause the method to be called twice. Setting it to
solves this.
Need to add code to check for Model.Image != null
Very strange!!

mvc select second table data using linq

/*
hallo, I am new in mvc and linq. I've 2 table in relation many to many: 1)employe 2)device
Selecting an employe I'd like to see his devices:
-Marco
-Franco
Selecting Marco should appear the devices associated to him.
My code (not work):
Controller:
*/
public ActionResult VediDevice(int id)
{
Impiegato impi = new Impiegato();
List<Device> ListDevice = new List<Device>();
using (DatabaseMVCCOntrolsEntities db = new DatabaseMVCCOntrolsEntities())
{
ListDevice= db.Devices.Where(u => db.ImpiegatiDevice.Any(m => m.impiegatiID == id)).ToList(); <---???
}
return View(ListDevice);
}
VediDevice.cshtml:
#model List<MVCControlToolkit.Models.Device>
#{
ViewBag.Title = "VediDevice";
}
<h2>VediDevice</h2>
<table class="table table-striped table-condensed">
<tr>
<th>
NOME
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.nome)
</td>
</tr>
}
</table>
Not work.
What should I do?
Thank you
Ale
Use Include before where
ListDevice= db.Devices.ToList().Where(u => u.item.Any(m => m.impiegatiID == id)).ToList();
and add your Device class
List<ImpiegatiDevice> item{get;set;}

Why is my statically typed partial view trying to render an unintended model type?

I have a partial view, in my ASP.NET MVC4 web app. It's just a partial view designed to display a table, given a collection of entities. It looks like this:
#model ICollection<Portal.Models.Matter>
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>Name</th>
<th>Last Accessed</th>
<th>Client</th>
</tr>
</thead>
<tbody>
#if (Model.Count > 0)
{
#Html.DisplayForModel()
}
else
{
<tr>
<td colspan="3" class="text-muted text-centered">There are no Matters to display.</td>
</tr>
}
</tbody>
</table>
I have a DisplayTemplate for Matter that is statically typed to the single Matter entity, and it handles rendering of each table row.
For some reason, when this partial is rendered, instead of using the Matter DisplayTemplate it just shows the following:
System.Collections.Generic.List`1[Portal.Models.Account]System.Collections.Generic.List`1[Portal.Models.Account]
Now, this partial is not even bound to a collection of Account entities. It's bound to a collection of Matter entities. So, why is #Html.DisplayForModel() trying to display for a collection of Accounts? At run time, using a debugger, I can see the Model is in fact a collection of Matter entities, not Account.
I render this partial using the following code:
#Html.Partial("~/Views/Matter/_Table.cshtml", Model.Client.Matters, new ViewDataDictionary())
I found a work around, or maybe a solution, not sure. Anyway, instead of using DisplayForModel on an ICollection, I iterate over the collection and use DisplayFor on each element.
For example ...
#model ICollection<Foo>
for (var item in Model)
{
#Html.DisplayFor(m => item)
}
I guess nothing is forcing you to use a property off of m in DisplayFor.

ASP.Net MVC EditorFor not working

I am trying to render a table, using EditorFor, and a partialview, I think.
I have a model with a List<> property defined like this:
public List<TransactionSplitLine> TransactionSplitLines { get; set; }
The idea is that a user selects a few drop downs and enters a value into an edit box, and clicks a button. The model goes back to the controller, and the controller adds the entered values to the List<>
[HttpPost]
public ActionResult AccountTransaction(AccountTransactionView model)
{
var reply = CreateModel(model);
if (model.CategoryIds != null)
{
foreach (var c in model.CategoryIds)
{
reply.TransactionSplitLines.Add(new TransactionSplitLine { Amount = "100", Category = "Test Category", SubCategory = "Test More", CategoryId = int.Parse(c) });
}
}
reply.TransactionSplitLines.Add(new TransactionSplitLine { Amount = "100", Category = "Test Category", SubCategory = "Test More", CategoryId = 1 });
return View("AccountTransaction", reply);
}
Ignore the CreateModel. It simply sets up some data. Also, I am hardcoding data. This will eventually come from some form values.
The model is then returned to the same screen, allowing the user to ender more data. Any items in the List<> are read and a Table is rendered. I also have to store the current listen item values in hidden fields, so that they can be submitted back, along with the new data entered, so that the list can grow each time the user adds data.
The view is defined like this:
<table width="600">
<thead>
<tr class="headerRow">
<td>
Category
</td>
<td>
Sub Category
</td>
<td>
Amount
</td>
</tr>
</thead>
<tbody>
<%=Html.EditorFor(m=>m.TransactionSplitLines) %>
</tbody>
</table>
This is my first attempt with EditorFor...
My View is in a folder 'Views/BankAccount/AccountTransaction.aspx
I have created a ascx in Views/Shared/TransactionSplitLines.ascx
The code for the ascx is like this:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<BudgieMoneySite.Models.TransactionSplitLine>" %>
<tr>
<td>
<%=Model.Category %>
<%=Html.HiddenFor(x => x.CategoryId)%>
</td>
<td>
<%=Model.SubCategory %>
<%=Html.HiddenFor(x => x.SubCategoryId)%>
</td>
<td>
<%=Model.Amount %>
<%=Html.HiddenFor(x => x.AmountValue)%>
</td>
</tr>
This is data
The 'This is data' is just test stuff, which is never rendered.
When I run this, all that happens is that my output is rendered as:
<table width="600">
<thead>
<tr class="headerRow">
<td>
Category
</td>
<td>
Sub Category
</td>
<td>
Amount
</td>
</tr>
</thead>
<tbody>
Test Category
</tbody>
</table>
It seems like the ascx isn't being used? I'd expect to see the 'This is data' text. But, nothing. Hopefully you can see an obvious fault?
Your editor template should be either:
~/Views/Shared/EditorTemplates/TransactionSplitLine.ascx
or:
~/Views/BankAccount/EditorTemplates/TransactionSplitLine.ascx
The name of the ascx is always the type name of the collection item (TransactionSplitLine and not TransactionSplitLines) and it should be situated at ~/Views/Shared/EditorTemplates or ~Views/ControllerName/EditorTemplates.
Or if you want to use a custom editor template name:
<%= Html.EditorFor(m=>m.TransactionSplitLines, "~/Views/foo.ascx") %>
Or use UIHintAttribute on your model.

ASP.NET MVC3 Deleting a record using a sub-form

I am trying to delete a record being displayed in a table on my ManageUser view using a sub-form, thus
<table cellpadding="2" cellspacing="0" border="1" summary="User Grid" style="text-align: left">
<tr style="background-color: #ABC3CB;">
<th align="center">User Name</th>
<th align="center">Approved</th>
<th align="center"> </th>
<th align="center"> </th>
</tr>
<% foreach(MembershipUser membershipUser in ViewData.Model) { %>
<tr>
<td><%: membershipUser.UserName %></td>
<td align="center"><%: Html.CheckBox(" ", true, membershipUser.IsApproved ) %></td>
<td align="center">
<% using (Html.BeginForm( "DeleteItem", "Admin", new { id = membershipUser.UserName } )) { %>
<input type="image" src="<%: Url.Content( "~/Content/Images/Delete.jpg" ) %>" />
<% } %>
</td>
</tr>
<% } %>
</table>
The ManageUser view is displayed by the following code in the AdminController, thus
public ViewResult ManageUser( string searchType, string searchInput )
{
List<SelectListItem> searchOptionList = new List<SelectListItem>()
{
new SelectListItem() {Value="UserName", Text = "UserName"},
new SelectListItem() {Value="Email", Text = "Email"},
};
ViewData["searchOptionList"] = new SelectList( searchOptionList, "Value", "Text", searchType ?? "UserName" );
ViewData["searchInput"] = searchInput ?? string.Empty;
ViewData["searchType"] = searchType;
MembershipUserCollection viewData;
if (String.IsNullOrEmpty( searchInput ))
viewData = Membership.GetAllUsers();
else if (searchType == "Email")
viewData = Membership.FindUsersByEmail( searchInput );
else
viewData = Membership.FindUsersByName( searchInput );
ViewData["PageTitle"] = "Account Management";
return View( viewData );
}
When I display the page, and select the Delete choice, I expect it to run Admin/DeleteItem in the AdminController, thus
public RedirectToRouteResult DeleteItem( string id )
{
Membership.DeleteUser( id );
return RedirectToAction( "ManageUser" );
}
but instead, it is returning directly to the Admin/ManagerUser view, thus displaying my original set of records again.
I have obviously missed something but I cannot see what. Anybody help?
HTML <form> elements cannot be nested. Nesting them results in unexpected behavior which could vary between different browsers. Quote from the specification:
Every form must be enclosed within a
FORM element. There can be several
forms in a single document, but the
FORM element can't be nested.
So you might need to remove the outer form or find another way of organizing your markup.

Resources