ASP.NET MVC Display HTML Based on User Role - c#

Following best practices, is there a better way to show/hide controls based on the user's role, or is it perfectly acceptable to use User.IsInRole() inside of a view? An answer on this post says it violates separation of concerns. What are the alternatives?
#if(User.IsInRole("Admin"))
{
#Html.ActionLink("Create", "Create", "Games")
}
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">Date</th>
<th scope="col">Home</th>
<th scope="col">Away</th>
<th scope="col">Field</th>
<th scope="col">Result</th>
#if (User.IsInRole("Admin"))
{
<th scope="col"></th>
}
</tr>
</thead>
<tbody>
#foreach (var g in Model)
{
<tr>
<th>#g.GameDate</th>
<th>#g.HomeTeam.TeamName</th>
<th>#g.AwayTeam.TeamName</th>
<th>#g.Ballpark.Name</th>
<th>(#g.HomeTeamRuns-#g.AwayTeamRuns) #g.Result</th>
#if (User.IsInRole("Admin"))
{
<th> #Html.ActionLink("Edit", "Edit", new { id = g.GameId })</th>
}
</tr>
}
</tbody>
</table>

Personally, I would add a bool property to the model IsAdmin and set the value in the controller. That way your View is only working with the Model.
#if (Model.IsAdmin)
{
// render admin elements
}

Related

How to use EditorFor to save changes to the Model?

I have a view like this:
#model IEnumerable<Namespace.MyClass>
#using Newtonsoft.Json;
<form asp-action="Update">
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Product)
</th>
<th>
#Html.DisplayNameFor(model => model.IsAvailable)
</th>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Product)
</td>
<td>
#Html.EditorFor(modelItem => item.IsAvailable)
</td>
</tr>
}
</tbody>
</table>
<div>
<a href=#Url.Action("SaveChanges", "Product", new {productList = JsonConvert.SerializeObject(Model) })> Save changes</a>
</div>
</form>
where SaveChanges looks like this:
[HttpGet] // Perhaps it should be HttpPost here, but if I change it to that nothing happens when I run the program after clicking the "Save changes" link
public ActionResult SaveChanges(string productList)
{
List<MyClass> products = JsonConvert.DeserializeObject<List<MyClass>>(productList);
// Here I continue with SqlCommand to later make an UPDATE to a database changing the value of IsAvailable which is the only adjustable value in my view
}
My issue is that when I run the program and I change IsAvailable (which is a bool) from false to true in my view and press "Save Changes", the model does not change, i.e. productList still has the value False for IsAvailable for that particular product.
Does anybody have an idea as to why? From my understanding if I have a and
Model information is not updated when you send the model to the action with the link. And the same initial amount is sent.
The changes you make to the model fields are only in the html controls and have nothing to do with the model. The model is updated when you post the form information.
I submitted the form to jQuery in the following code
in view
#model List<Namespace.MyClass>
#using (Html.BeginForm("SaveChanges", "Product", FormMethod.Post))
{
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.FirstOrDefault().Product)
</th>
<th>
#Html.DisplayNameFor(model => model.FirstOrDefault().IsAvailable)
</th>
</thead>
<tbody>
#for (int i = 0; i < Model.Count(); i++)
{
<tr>
<td>
#Html.DisplayFor(modelItem => Model[i].Product)
</td>
<td>
#Html.EditorFor(modelItem => Model[i].IsAvailable)
</td>
</tr>
}
</tbody>
</table>
<div>
#Html.ActionLink("Save changes", "", null, new { #id = "submit"})
</div>
}
#section scripts{
<script type="text/javascript">
$("#submit").click(function () {
document.forms[0].submit();
return false;
});
</script>
}
action in controller
[HttpPost] // Perhaps it should be HttpPost here, but if I change it to that nothing happens when I run the program after clicking the "Save changes" link
public ActionResult SaveChanges(IEnumerable<MyClass> products)
{
// Here I continue with SqlCommand to later make an UPDATE to a database changing the value of IsAvailable which is the only adjustable value in my view
}

Marking Rows as Selected Before Table Render

I am using Bootstrap-Table Cn
I have a table. I want to pre-check certain rows. However when I add class="selected" to my or table row, upon loading the table in, Bootstrap-Table removes the class selected and unchecks it. How can I preserve the initial checkbox selected, before the table loads?
Update: I am not creating checkbox inputs. I am using BootStrap Tables CN to generate the checkboxes for me.
Here is the code.
<table id="storeTable" class="table table-bordered table-hover" style="width:100%" data-toggle="table" data-search="true" data-toolbar="#toolbar" data-pagination="true" data-side-pagination="client" data-show-pagination-switch="true" data-page-list="[10, 25, 50, ALL]" data-click-to-select="true" data-filter>
<thead>
<tr>
<th data-sortable="true" data-checkbox="true">
</th>
<th data-field="cg" data-sortable="true">
#Html.DisplayNameFor(model => model.dealeradminstore[0].cg)
</th>
<th data-field="sn" data-sortable="true">
#Html.DisplayNameFor(model => model.dealeradminstore[0].serial_number)
</th>
<th data-field="name" data-sortable="true">
#Html.DisplayNameFor(model => model.dealeradminstore[0].Name)
</th>
<th data-sortable="true">
WebReports
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.dealeradminstore)
{
<tr id="#test.NullRefExcl(item.serial_number.ToString())" checked>
<td></td>
<td>
#test.NullRefExcl(item.cg.ToString())
</td>
<td>
#test.NullRefExcl(item.serial_number.ToString())
</td>
<td>
#test.NullRefExcl(item.Name)
</td>
<td>
#{string reportsCheck = "";
if (test.NullRefExcl(item.base_xtags).Contains("RPT"))
{
reportsCheck = "Yes";
}
if (!test.NullRefExcl(item.base_xtags).Contains("RPT"))
{
reportsCheck = "No";
}
}
#test.NullRefExcl(reportsCheck)
</td>
</tr>
}
</tbody>
</table>
To create a dynamically generated checkbox with it's value already set to checked:
#Html.CheckBoxFor(m => m.SomeBooleanProperty, new { #checked = "checked" });
Source: Proper usage of .net MVC Html.CheckBoxFor
Finally with a point in the right direction from Richard0096 I was able to figure it out. Here is the solution that uses the Bootstrap Tables Extensions CN.
var checkSum = 0;
function checkedFormatter(value, row, index) {
var snList = [];
snList = document.getElementById("inputsn").value.split("|");
snList.forEach(function (element) {
var checkSN = ((row.sn).toString()).trim();
if (checkSN == element) {
checkSum = 1;
}
})
if (checkSum == 1) {
checkSum = 0;
return {
checked: true
}
}
return value;
}

Get cell DisplayName from strongly-typed-list cell by List only (empty list)

I have a list of "Book" (e.g.) as a model in view
#model List<Book>
I want to create a table that each column get it's header by Book's DisplayName propery:
<tr>
<th class="text-right">
#Html.DisplayNameFor(modelItem => Model.someMetaData.lineNumber)
</th>
<th class="text-right">
#Html.DisplayNameFor(modelItem => Model.someMetaData.FirstName)
</th>
<tr>
You can use DisplayNameFor helper method when your model is of type IEnumerable<T>
#model IEnumerable<Book>
<table class="table table-responsive table-striped">
<tr>
<th>#Html.DisplayNameFor(a=>a.Id)</th>
<th>#Html.DisplayNameFor(a => a.Name)</th>
</tr>
#foreach (var b in Model)
{
<tr>
<td>#b.Id</td>
<td>#b.Name</td>
</tr>
}
</table>
This works only if your view is strongly typed to an IEnumerable<Book>, It will not work for List<Book>

Get object inside partial View

Friends,
I have a View page called "OtherDatas.cshtml" and i need to render a PartialView inside her. So, to make this, i need to check if the object inside partialView is null or not. If not, the partialView Appears. How can i get the object inside the partialView? Here is my code:
OtherDatas.cshtml:
<div class="table-responsive">
#{
if (//I need to check the object inside ){
Html.Partial("~/Views/Outrosdados/Search.cshtml");
}
else
{
<table class="table table-striped">
<tr>
<th style="min-width:130px;">Mês</th>
<th style="min-width:80px;">Amortização</th>
<th style="min-width:100px;">Recebimento do Mês</th>
<th style="min-width:100px;">Atraso</th>
<th style="min-width:100px;">DAMP3</th>
</tr>
</table>
}
}
</div>
PartialView Search.html:
#model TB_DADOS_MANUAIS
#using EixoX.Html;
#using Gestão.Models;
#using System.Globalization;
#{
List<TB_OUTROS_DADOS> od = (List<TB_OUTROS_DADOS>)ViewData["outrosDados"];
Bootstrap3Presenter<TB_OUTROS_DADOS> presenter =
Bootstrap3Presenter<TB_OUTROS_DADOS>.GetInstance("pt-BR");
ViewBag.Title = "Outros Dados";
}
<table class="table table-striped">
<tr>
<th style="min-width:130px;">Mês</th>
<th style="min-width:80px;">Amortização</th>
<th style="min-width:100px;">Recebimento do Mês</th>
<th style="min-width:100px;">Atraso</th>
<th style="min-width:100px;">DAMP3</th>
</tr>
#foreach (TB_OUTROS_DADOS dados in od){
<tr>
<td>#dados.DT_MES_UTILIZACAO.ToString(CultureInfo.CreateSpecificCulture("pt-BR"))</td>
<td><span class="money" />#dados.VL_AMORTIZACAO</td>
<td><span class="money" />#dados.VL_RECEBIMENTO_MES</td>
<td><span class="money" />#dados.VL_ATRASO</td>
<td><span class="money" />#dados.VL_DAMP3</td>
</tr>
}
</table>
I need to check inside of the 'foreach' if i have some 'TB_OUTROS_DADOS' inside the 'od' list.
Thanks!
You can't do that in this way.
Pass List<> as model to you parent view or declare this list in same way like in partial view then do check, and if it is good pass it to partial view.
In this way:
#{
List<TB_OUTROS_DADOS> od = (List<TB_OUTROS_DADOS>)ViewData["outrosDados"];
<div class="table-responsive">
#{
if (od.Count > 0){
Html.Partial("~/Views/Outrosdados/Search.cshtml",od);
}
else
{
<table class="table table-striped">
<tr>
<th style="min-width:130px;">Mês</th>
<th style="min-width:80px;">Amortização</th>
<th style="min-width:100px;">Recebimento do Mês</th>
<th style="min-width:100px;">Atraso</th>
<th style="min-width:100px;">DAMP3</th>
</tr>
</table>
}
}
</div>
And in PartialView
#model List<TB_OUTROS_DADOS>
#using EixoX.Html;
#using Gestão.Models;
#using System.Globalization;
#{
Bootstrap3Presenter<TB_OUTROS_DADOS> presenter =
Bootstrap3Presenter<TB_OUTROS_DADOS>.GetInstance("pt-BR");
ViewBag.Title = "Outros Dados";
}
<table class="table table-striped">
<tr>
<th style="min-width:130px;">Mês</th>
<th style="min-width:80px;">Amortização</th>
<th style="min-width:100px;">Recebimento do Mês</th>
<th style="min-width:100px;">Atraso</th>
<th style="min-width:100px;">DAMP3</th>
</tr>
#foreach (TB_OUTROS_DADOS dados in Model){
<tr>
<td>#dados.DT_MES_UTILIZACAO.ToString(CultureInfo.CreateSpecificCulture("pt-BR"))</td>
<td><span class="money" />#dados.VL_AMORTIZACAO</td>
<td><span class="money" />#dados.VL_RECEBIMENTO_MES</td>
<td><span class="money" />#dados.VL_ATRASO</td>
<td><span class="money" />#dados.VL_DAMP3</td>
</tr>
}
</table>

Razor get value of input HTML bounded by foreach

I have one following table html, the data of rows in the table is looped by foreach.
Can I use Razor to get the value of each row into a List or an array in C#?
My C# code Razor (I tried this so far)
#{
var l = new List<string>();
l.Add(#<input id="updated_value2" data-bind="value:value,visible:isEditing()" />);
}
Here's my table
<table class="table table-hover">
<tbody data-bind="foreach: $root.mapJsons(parameters())">
<tr class="data-hover">
<td>
<strong>
<span data-bind="text:key" />
</strong>
</td>
<td>
#*display label and input for dictionary<value> false DIS true APP*#
<input id="updated_value" data-bind="value:value,visible:isEditing()" />
<label id="display_value" data-bind="text:value,visible:!isEditing()" />
</td>
</tr>
</tbody>
<thead>
<tr>
<th style="width: 30%">
Name
</th>
<th style="width: 30%">
Value
</th>
<th></th>
</tr>
</thead>
</table>
Your foreach loop is being executed client-side (looks like a KnockoutJS binding?) rather than server-side, so any Razor code you embed in the table is only going to be called once as it's rendered by the server. So the answer is no, you cannot populate a server-side list with this particular foreach loop.

Categories