How to know who goes on pages? - c#

I'm new in C#, specifically in MVC.
I want to return a view with a model like that :
public ActionResult Index()
{
return View(db.MyModel.Where(a => a.EmployeID == m_idEmployee));
}
for a specific employee (where m_idEmployee is the id of employee/user, but for the moment, it's a value that I set myself)
I don't use the loggingaccount method from visual studio (not very clear for me)
So I want to know if I can "pass" value in Index to set m_idEmployee (from my View for example).

You can pass the employee id to your Index method like:
public ActionResult Index(int empId)
{
return View(db.MyModel.Where(a => a.EmployeID == empId));
}
you have to change the way you call the Index method accordingly by passing it as query string or alternatively change the verb to post; the model binder will take care of it.
Modelbinder quick ref:
Maps a browser request to a data object. This class provides a
concrete implementation of a model binder.

Change your controller method to:
public ActionResult Index(int employeeId)
Then create an action in your view:
#Html.ActionLink("Text of the link", "Index", "NameOfYourController", new { employeeId = 123 })

you can create a Class return value in a class independente
and call the function in your controller class like this
EmployerModel.class
public findEmployerById(int id){
return db.MyModel.Where(a => a.EmployeID == id);
}
public ActionResult Index(int id)
{
return View(new EmployerModel().findEmployerById(id));
}
and in your view you need to add
#model package.MyModel

Related

ASP.Net MVC: pass information to HTTPost Controller

Here is my scenario: I have a model called MaterialPaymentRequest. It consists of several MaterialPaymentRequestSubItem so PaymentRequest is parent and MaterialPaymentRequestSubItem are its children.
Consider when I have a MaterialPaymentRequest and I want to add a child to it.
Currently its method inside MaterialPaymentRequestSbuItemController looks like this:
public ActionResult CreateChild(int parentId)
{
if (parentId==null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
var parenetRequest = (from request in db.MaterialPaymentRequests
where request.Id==parentId
select request);
ViewBag.MaterialPaymentRequestId = new SelectList(parenetRequest, "Id", "Description", parentId);
ViewBag.ParentID = parentId;
return View();
}
My problem is inside view, user can change its parent since I have a dropdown which I cannot freeze it or make it readonly:
#Html.DropDownList("MaterialPaymentRequestId", String.Empty)
I've tried to use a ViewModel and after post I set parentID of my chil however this way I don't know how to pass ParentId to http-post controller method.
My postback method before using ViewMode is like this:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateChild([Bind(Include = "Id,Name,Unit,UnitPrice,MaterialPaymentRequestId,Quantity")] MaterialPaymentRequestSubItem materialpaymentrequestsubitem)
{
if (ModelState.IsValid)
{
...
}
....
}
I've seen methods like this which use Html.Hidden but i think it is not secure enough since user can manipulate information at user-side.
Are there any better method to do this?
Can I pass information to a controller which accept parentID as parameter with declarion like this?
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateChild(int parentID, [Bind(Include = "Id,Name,Unit,UnitPrice,MaterialPaymentRequestId,Quantity")] MaterialPaymentRequestSubItem materialpaymentrequestsubitem)
{
if (ModelState.IsValid)
{
...
}
....
}
To make a HTML helper input control read only on client side, use the following:
#Html.DropDownList("MaterialPaymentRequestId", String.Empty, new { #readonly = "readonly" })
I suggest you to maintain parentId content state in server side with Session variable if you don't want to use client-side hidden fields.
Session["parentId"] = parentId;
// just an example to extract Session variable
int parentId = Session["parentId"] != null ? Convert.ToInt32(Session["ParentId"]) : return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
However if you need the hidden field inside your view, use encoded text in hidden field with validation schema against its value (e.g. Base64 or better encodings), thus any user visiting your site can't easily alter the value in client-side.
View:
#Html.Hidden("ParentID", #ViewBag.ParentID);
// or if you have a viewmodel, pass viewmodel's value here
#Html.HiddenFor(model => model.ParentID);
Controller method:
public ActionResult CreateChild(int parentId)
{
...
// convert parentId into Base64
ViewBag.ParentID = Convert.ToBase64String(parentId);
return View(ViewBag); // model binding
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult CreateChild([Bind(Include = "Id,Name,Unit,UnitPrice,MaterialPaymentRequestId,Quantity,ParentID")] MaterialPaymentRequestSubItem materialpaymentrequestsubitem)
{
...
// get Parent ID
int parentId = (int)Convert.FromBase64String(ParentID);
// write your own algorithm to validate hidden field's value
...
if (ModelState.IsValid)
{
// redirect to create child elements
return RedirectToAction("CreateChild", "Controller", new { #id = parentId });
}
}
Hope this explanation useful for you, CMIIW.

Asp.net Create ActionResult parameters dictionary contains a null entry for parameter

I have not changed my code, which used to work, I even clarified this with an earlier build of the project. However, I now get this error:
The parameters dictionary contains a null entry for parameter 'recipeID' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Create(Int32, BareCupboard.Models.RecipeStep)' in 'BareCupboard.Controllers.RecipeStepController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters
My code is:
[HttpPost]
public ActionResult Create(int recipeID, RecipeStep newRecipeStep)
{
try
{
var recipe = db.Recipes.Single(r => r.recipeID == recipeID);
recipe.RecipieSteps.Add(newRecipeStep);
db.SaveChanges();
return RedirectToAction("Index", "Recipe");
}
catch
{
return View();
}
}
I tried: int? recipeID, but this fails to work.
Any ideas what might have happened as all I can see is mysticism at play here!
Check your view code for the order of the parameters. The model binder needs it come in proper order. It is very easy to make mistake there.
Update
Here one way of resolving this. Create a view model as below:
public class RecipeViewModel
{
public int RecipeId { get; set; }
public RecipeStep RecipeStep { get; set; }
}
In the controller you will have the following:
public ActionResult Create()
{
var recipeId = 10 // however you want to select that Id
var recipeViewModel = new RecipeViewModel {RecipeId = 10}
return View(recipeViewModel);
}
[HttpPost]
public ActionResult Create(int recipeID, RecipeStep newRecipeStep)
{
//your code
}
In the view you can do the following:
#model MvcApplication3.Models.RecipeViewModel
#using (Html.BeginForm(null,null,FormMethod.Post))
{
<div>
<p>#Html.HiddenFor(x=>x.RecipeId) </p>
<p>#Html.TextBox("RecipeStepData1")</p>
<p>#Html.TextBox("RecipeStepData2")</p>
<p>#Html.TextBox("RecipeStepData3")</p>
</div>
<input type="submit" value="Submit" id="btn" />
}
Notice the order. I put the id first and then rest of the recipe step data so it gets bind properly.
For the begin form, You dont have to specify action and controller as you are doing the post on the same page. It doesnt hurt if you put there.
Hope this helps... :)
Why recipeID is null in in your posted data? It is your problem and
var recipe = db.Recipes.Single(r => r.recipeID == recipeID) cannot get recipeID=null because r.recipeID is not nullable.

How does my view know what type of data is being returned using MVC?

So I created a project to test DI in MVC 4. Yeah, that was the easy part. I have a controller that looks like this.
public class CompanyManagementController : Controller
{
private ICompanyService companyService;
public CompanyManagementController(ICompanyService companyService)
{
this.companyService = companyService;
}
public ActionResult Index()
{
return View(companyService.GetCurrentCompanies());
}
}
What I can't figure out is how to tell the view Index.cshtml that I have this List that I am returning to it. When I have just a POCO it's easy. I did this
[HttpGet]
public ActionResult Create()
{
var company = new Company();
return View(company);
}
[HttpPost]
public ActionResult Create(Company company)
{
using(var context = new InventoryContext())
{
context.Companies.Add(company);
context.SaveChanges();
}
return View("Create");
}
That was super easy because I just said
#model MvcInventoryManager.Models.Company
in the Create.cshtml file.
Any hints? What I want to do is be able to loop through the list of companies that get returned.
Thanks!
What is the return type of companyService.GetCurrentCompanies()? That would be the type you'd want to use for binding the Model in the view. For example, if the type is IEnumerable<Company> then in your view you would declare this:
#model IEnumerable<MvcInventoryManager.Models.Company>
That way the type of the Model property would match what's being passed to the view and you could loop through the Model:
foreach (var company in Model)
after declaring your model in the view just loop through it like so:
#foreach (var company in Model)
{
Html.DisplayFor(modelItem => company.companyID)
Html.DisplayFor(modelItem => company.CompanyName)
}

Pass UserId to the Model

So I have a simple web app where I can create a user (UserModel) and it returns that user ID. The user then has the ability to enter multiple instances or records of a specific item type, in this case a geographic location (LocationModel). The LocationModel has a UserId property that I need to set when the location is created.
The ActionLink for creating a user is User/Create/id=[userid]
The code in the controller is currently.
[HttpGet]
public ActionResult Create(string id)
{
return View();
}
[HttpPost]
public ActionResult Create(LocationModel model)
{
//CODE TO SAVE MODEL
}
My questions is how to pass the user id so that I can get it into the model in order to relate the two. I was going to try to pass it in the ViewBag and render it in a Hidden field but was thinking that someone has to have a more elegant solution than this. Thanks in advance.
Put the UserId on the model, and pass the model to the view:
[HttpGet]
public ActionResult Create(string id)
{
return View(new LocationModel{UserId = id});
}
Then render the UserId property as a hidden field in the View, so it will get included on your model parameter when the form is POSTed.
#model LocationModel
#using (Html.BeginForm(...)) {
#Html.HiddenFor(m => m.UserId)
...
}

Display FormCollection with ASP.NET MVC

I have a form using Html.BeginForm() on a view. I have in the controller an ActionResult to handle the post. What I need is to just kick back the results to a view. I can kick off the new view, but I don't know how to pass the data to it and once there I don't know how to display it. Here's what I have in the ActionResult.
[HttpPost]
public ActionResult Index(FormCollection collection)
{
ViewBag.Title = "Confirm your order";
return View("OrderConfirmation", collection);
}
If I just do a return View("OrderConfirmation"); it will go to the view so I know I got that working. I just don't know how to pass the data. Right now I have it strongly typed to the same model the form was which causes errors because this FormCollection is not the same obviously. If I remove the strongly typed line the above works, but I have no idea how to loop through the collection at that point.
Thanks for the help.
Use a ViewModel and a stongly typed view. Then you can pass the model to the second view.
public ActionResult Index(Order order)
{
return View("OrderConfirmation", order);
}
ASP.NET MVC will automatically create an order instance and fill the properties from the posted FormCollection.
First don't use FormsCollection, its too generic. You only need it if you need to unit test and access UpdateModel().
Bind to a model type or bind to params:
public ActionResult Index(SomeModel model)
{
return View("OrderConfirmation", model);
}
or
public ActionResult Index(int key)
{
SomeModel model = new SomeModel();
UpdateModel(model);
return View("OrderConfirmation", model);
}
in your view at the top specify
#model MyAppNameSpace.ViewModels.SomeModel

Categories

Resources