I am using ASP.NET MVC 4 Runtime, and writing encrypted data to my database using a function.
public string Encrypt(string encryptMe)
{
return Helpers.Encryptor.Encrypt(encryptMe);
}
On return the data is displayed like so:
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Phone)
</td>
<td>
#Html.DisplayFor(modelItem => item.Name)
I want to decrypt the data before displaying it here using the following function:
public static string Decrypt(string decryptMe)
{
return Helpers.Encryptor.Decrypt(decryptMe); ;
}
How can I decrypt my data?
Add a Property in the model called for example "DecryptedPhone".
This will only have a Get and will call the decrypting function:
public string DecryptedPhone
{
get
{
return Decrypt(Phone);
}
}
private string Phone;
The phone will be private so that it cannot be accessed.
In your controller's method, before the return View(model); line, you can decrypt the properties. It would be something like this:
foreach (var item in model)
{
item.Phone = Decrypt(item.Phone);
item.Name = Decrypt(item.Name);
}
return View(model);
Related
I'm creating web-client for my REST API, and I want to add a field to my table containing result of async function.
#foreach(Product item in products)
{
<tr>
<th>#item.Name</th>
<th>#item.Amount</th>
<th>#GetUnit(item.UnitID).Result</th>
<th>#item.PriceNetto</th>
</tr>
}
async Task<string> GetUnit(Guid id)
{
string a = "https://localhost:5001/api/Units/";
a += id.ToString();
var temp = await Http.GetJsonAsync<Unit>(a); //it fails here
return temp.Name;
}
In short I have a list of products and items on the list have "UnitID" property which I use to make a GET request. When I put anywhere in code .Result after my async function result Visual Studio's debugger just skip the line responsible for calling the API and 'bricks' whole app without any error nor exception. Then I have to restart the project.
I tried to create second function only for returning GetUnit(id).Result but it gave nothing. I tried to return whole Unit object and then in the table GetUnit(item.UnitID).Name but it was just representing object (I guess...). I seems like all I need is do it with .Result but when I do it doesn't work.
My API is made with .Net Core 2.2 and my client is made with .Net Core 3.0 (Blazor template). Is this a bug or I just can't do it that way? Thanks.
you shouldn't need to do it.i recommand to call it in async action,like below :
razor focus on view,controller/model focus on data.
public async Task<IActionResult> SomeAction(Guid id)
{
var products = ..;
foreach (var item in products)
{
p.UnitID = await GetUnit(item.UnitID);
}
return View(products);
}
private async Task<string> GetUnit(Guid id)
{
string a = "https://localhost:5001/api/Units/";
a += id.ToString();
var temp = await Http.GetJsonAsync<Unit>(a); //it fails here
return temp.Name;
}
public class Product
{
public string Name { get; set; }
public decimal Amount { get; set; }
public string UnitID { get; set; }
public string PriceNetto { get; set; }
}
IMO, you can't do that way.In blazor,you could get all data in OnInitializedAsync instead.Store all Name in a string List and display the list data in view based index.For example:
#code {
private List<string> listItems = new List<string>();
protected override async Task OnInitializedAsync()
{
//get products
foreach (var product in products)
{
string a = "https://localhost:5001/api/Units/";
a += product.UnitID.ToString();
var temp = await Http.GetJsonAsync<Unit>(a);
listItems.Add(temp.Name);
}
}
}
Razor
#{ int i = 0;}
#foreach(Product item in products)
{
<tr>
<th>#item.Name</th>
<th>#item.Amount</th>
<th> #listItems[i] </th>
<th>#item.PriceNetto</th>
</tr>
i++;
}
So I'm new to ASP and EF and I am wondering how to do this incredibly basic operation, as well as a few questions to go along with doing it.
Currently I have a table we will call Resource;
class Resource
{
int current;
int min;
int max;
};
Right now I have the default CRUD options for this. What I would like is a + / - button on the main list that will manipulate the current value of each resource and update the value in the DB and on screen.
There are also certain operations I'd like to run such as "AddFive" to a selected group of resources.
So my questions;
How do I do this?
Is this scalable? If someone is constantly hitting the buttons this is obviously going to send a lot of requests to my DB. Is there any way to limit the impact of this?
What are my alternatives?
Thanks.
Edit:
To clarify the question; here are my post functions. How / where do I add these in my view to get a button showing for each resource. I just want the action to fire and refresh the value rather than redirect to a new page.
#Html.ActionLink("+", "Increment", new { id = item.ID })
public void Increment(int? id)
{
if (id != null)
{
Movie movie = db.Movies.Find(id);
if (movie != null)
{
Increment(movie);
}
}
}
[HttpPost, ActionName("Increment")]
[ValidateAntiForgeryToken]
public ActionResult Increment([Bind(Include = "ID,Title,ReleaseDate,Genre,Price")] Resource resource)
{
if ((resource.Current + 1) < (resource.Max))
resource.Current++;
return View(resource);
}
It sounds like the main issue you are having is creating a list of movies on the front end and updating the details for a specific one.
The key here is that you will need to either wrap a form around each item and have that posting to your update controller or use ajax / jquery to call the controller instead.
I have given you an example of the first one. Once the update controller is hit it will redirect to the listing page which will then present the updated list of movies.
Below is a minimal working example of how to wire this up. I've not included any data access code for brevity but have included psuedo code in the comments to show you where to place it.
Please let me know if you have any futher questions.
Controller
public class MoviesController : Controller
{
public ViewResult Index()
{
// Data access and mapping of domain to vm entities here.
var movieListModel = new MovieListModel();
return View(movieListModel);
}
public ActionResult Increment(IncrementMovieCountModel model)
{
// Put breakpoint here and you can check the value are correct
var incrementValue = model.IncrementValue;
var movieId = model.MovieId;
// Update movie using entity framework here
// var movie = db.Movies.Find(id);
// movie.Number = movie.Number + model.IncrementValue;
// db.Movies.Save(movie);
// Now we have updated the movie we can go back to the index to list them out with incremented number
return RedirectToAction("Index");
}
}
View
#model WebApplication1.Models.MovieListModel
#{
ViewBag.Title = "Index";
}
<h2>Some Movies</h2>
<table>
<tr>
<td>Id</td>
<td>Name</td>
<td>Increment Value</td>
<td></td>
</tr>
#foreach (var movie in Model.MovieList)
{
using (Html.BeginForm("Increment", "Movies", FormMethod.Post))
{
<tr>
<td>#movie.Id #Html.Hidden("MovieId", movie.Id)</td>
<td>#movie.Name</td>
<td>#Html.TextBox("IncrementValue", movie.IncrementValue)</td>
<td><input type="submit" name="Update Movie"/></td>
</tr>
}
}
</table>
Models
public class MovieListModel
{
public MovieListModel()
{
MovieList = new List<MovieModel> {new MovieModel{Id=1,Name = "Apocalypse Now",IncrementValue = 3}, new MovieModel {Id = 2,Name = "Three Lions", IncrementValue = 7} };
}
public List<MovieModel> MovieList { get; set; }
}
public class MovieModel
{
public int Id { get; set; }
public string Name { get; set; }
public int IncrementValue { get; set; }
}
public class IncrementMovieCountModel
{
public int IncrementValue { get; set; }
public int MovieId { get; set; }
}
I am using MVC 4 Visual Studio 2012 with Razor.
I am generating a table based off of several tables pulled into a dataset from a remote call to a SQL server.
I want to be able to output these tables onto the webpage and then create two columns of checkboxes beside them in order to assign them to one area or another (it essentially sorts data into accepted and not accepted, while allowing some to continue pending if a decision has not been made).
I currently have all the tables in the dataset being assigned to datatables in the controller and then exported to the razor page. I do not have a model set up for this as of yet and I'm not sure what I would require in one if I did.
This is my current View:
#{
ViewBag.Title = "Requisitions";
}
<table class="table">
<thead>
<tr>
#foreach (System.Data.DataColumn col in Model.Columns)
{
<th class ="td">#col.Caption</th>
}
</tr>
</thead>
<tbody>
#foreach(System.Data.DataRow row in Model.Rows)
{
<tr>
#foreach (var cell in row.ItemArray)
{
<td class="td">#cell.ToString()</td>
}
</tr>
}
</tbody>
</table>
This is my current controller:
DataTable R = new DataTable();
public void GetData()
{
string connString = "Data Source=.;database=dataBase;Integrated Security=SSPI";
DataSet dataset = new DataSet();
SqlDataAdapter adapter = new SqlDataAdapter("dbo.procApprovalSelectPending", connString);
using (adapter)
{
adapter.SelectCommand.CommandType = CommandType.StoredProcedure;
adapter.Fill(dataset);
}
int count = dataset.Tables.Count;
for (int i = 0; i < dataset.Tables.Count; i++)
{
// Do something for each recordset (11 recordsets)
if (i == 0)
{
R = dataset.Tables[i];
}
}
dataset.Dispose();
adapter.Dispose();
}
public ActionResult Rs()
{
GetData();
return View(R);
}
I have more datatables than shown but they were removed to conserve space.
To sum it up, I would like two checkbox columns that are aligned with each row that is created from the datatable that allow me to choose that portion of data to send back to the server what has been changed with it, and creating a dynamic checkbox for each row was giving me an error such that :
#foreach(System.Data.DataRow row in Model.Rows)
{
<tr>
#foreach (var cell in row.ItemArray)
{
<td class="td">#cell.ToString()</td>
}
<td class="td">#Html.CheckBoxFor(m => m.Checkbox)</td>
</tr>
}
"An expression tree may not contain a dynamic operation"
Thanks in advance!
You should create a view model to represent the properties you want to display, including 2 additional boolean properties for 'accepted' and 'not accepted'. Assuming your columns are ID and Name
public class MyModel
{
public int ID { get; set; }
public string Name { get; set; }
public bool Accepted { get; set; }
public bool NotAccepted { get; set; }
}
and create a collection based on each row in your table that you want to display
public ActionResult Rs()
{
List<MyModel> items = new List<MyModel>();
// Populate items from your datatable
return View(items);
}
then in your view
#model List<MyModel>
#using (Html.BeginForm()
{
<table>
#for (int i = 0; i < Model.Count; i++)
{
<tr>
<td>#Html.TextBoxFor(m => m[i].ID)</tr>
<td>#Html.TextBoxFor(m => m[i].Name)</tr>
<td>#Html.CheckBoxFor(m => m[i].Accepted)</tr>
<td>#Html.CheckBoxFor(m => m[i].NotAccepted)</tr>
</tr>
}
</table>
<input type="submit" value="Save" />
}
then in your post method
[HttpPost]
public ActionResult Rs(List<MyModel> model)
{
foreach(MyModel item in model)
{
if(item.Accepted) {.. // do something
else if (item.NotAccepted) { .. // do something else
else {.. // do another thing
}
}
Use Following pattern
I have Created one static Class that is called as CommonUtilities it is giving me FormCollection,Checkboxname and valueofKey
public static class CommonUtilities
{
public static List<string> GetCheckboxSelectedValue(FormCollection frm, string checkboxname, string value)
{
List<string> retls = new List<string>();
var fileIds = frm[value].Split(',');
var selectedIndices = frm[checkboxname].Replace("true,false", "true").Split(',').Select((item, index) =>
new {
item= item,
index= index
}).Where(row=>row.item =="true")
.Select(row => row.index).ToArray();
if (selectedIndices.Count() > 0)
{
retls.AddRange(selectedIndices.Select(index => fileIds[index]));
}
return retls;
}
}
the above Function will be applied as below
Controller
List<string> selectedKeypair = CommonUtilities.GetCheckboxSelectedValue(frm, "m.BoolSelectedVal", "m.Key");
view
#foreach (MVCCareerModule.Models.Requirement m in Model.RequirementSearchResult)
{
<tr>
<td>
#Html.CheckBoxFor(modelitem => m.Apply)
#Html.HiddenFor(modelitem => m.Req_ID, new { Value = m.Req_ID })
</td>
</tr>
}
You will receive all Selected IDs in selectedKeypair
I would like to add an extension method for the html helper to customize a table, i add this method:
public static class HtmlElements
{
public static string Table(this HtmlHelper ht, string classe)
{
var table = new HtmlTable();
table.Attributes.Add("class", classe);
return table.InnerHtml;
}
}
When i'd like to use it like this
#using(#Html.Table("table_data")){
}
i have an error which indicates that i have to convert a string to IDisposable type.
What are the reasons of this error?
How can i fix it?
Edit
the full view's code :
using(var table = #Html.Table("table_data")){
<tr>
<th>Description</th>
<th>Client</th>
<th>Statut du client</th>
<th>Etat de test</th>
<th></th>
</tr>
for (int i = Model[2] - 5; i < Model[2]; i++)
{
if(i < Model[1].Count)
{
<tr style="font-size: 12px; padding:0px; ">
<td>#Model[0][i].PDescription</td>
<td>#Model[0][i].Nom_client</td>
<td>#Model[0][i].Statut_client</td>
<td style="color:red">#Model[1][i]</td>
<td>
#Model[0][i].Statut_client
</td>
</tr>
}
}
}
Your method returns a string, and when you use using in C#, that means you are insantiating an object that implements IDisposable, which string does not.
You are not doing anything with the string either. If you intend to build up an HtmlTable and do something with that, you must modify your code, for instance like so:
public static HtmlTable Table(this HtmlHelper ht, string classe)
{
var table = new HtmlTable();
table.Attributes.Add("class", classe);
return table;
}
and then you must use that in your code, like so:
#using(var table = #Html.Table("table_data")){
}
and within the brackets, you can now access the variable table.
public static class HtmlElements
{
public static HtmlTable Table(this HtmlHelper ht, string classe)
{
var table = new HtmlTable();
table.Attributes.Add("class", classe);
return table;
}
}
What about if I have a navigation property? I have a collection of another model in the model I'm trying to edit. I want to display a list of checkboxes for each object in the collection property. So far, this is what I tried...
#{
foreach (var category in ViewBag.Categories)
{
if (Model.Categories.Contains(category))
{
<input type="checkbox" name="selected-categories" value="category.CategoryId" checked="checked" />#category.Name
}
else
{
<input type="checkbox" name="selected-categories" value="#category.CategoryId" />#category.Name
}
}
}
But it fails with an EntityCommandExecutionException. In my if statement, how can I access the model.Categories like I do in something like #Html.EditorFor(model => model.Id)???
Using a strongly-typed View is the way I'd go. Create a ViewModel that contains your Model and use this ViewModel for the strongly-typed View.
Domain Model and ViewModel (simplified)
public class YourModel
{
string Category { get ; set ; }
}
public class YourViewModel
{
public List<string> PossibleCategories { get ; set ; }
public YourModel YourData { get ; set ; }
}
Then the View:
#model YourViewModel
#{
foreach (string CurrCategory in Model.PossibleCategories)
{
if (Model.YourData.Category == CurrCategory)
{
#Html.CheckBox(CurrCategory, new { #checked = "checked" })
#Html.Encode(CurrCategory) <br />
}
else
{
#Html.CheckBox(CurrCategory, false)
#Html.Encode(CurrCategory) <br />
}
}
}