MVC Passing Data while opening a page - c#

Hi I'm fairly new to MVC 5, I know how to pass data from my entities to a single view but I am now trying to create a button that opens a new view and also passes some info. I was wondering what some good ways to do this are.
I have model Position that has
positionId,
positionName,
positionDescription,
storeLocation
and a second model that is a job application
I want to create a button in my position details index that will open my application create page and pass in the positionId to be used locally in the application.
So my thought is to create a constructor for application that takes an int Id and use a this.appliedPositionId = id; or something like that. The issue is I'm not sure how to pass that info using a button to the view. I've tried Redirect and RedirectAction but I think I am using them wrong.

#Html.ActionLink("Create", "Create", "yourController", new { id = Model.PositionId }, null)
assuming you have a public ActionResult Create (int id) { ... } method –
Stephen Muecke answered solved it, thank you.

Related

Keeping controller in scope

Yesterday i was working on my asp.net mvc application where i was trying to cache some data in a field while a certain controller was in scope. The field kept clearing every time a new view got opened.
Question:
Is it possible to keep your Controller in scope while you're browsing Views that are handled by said Controller?
private static List<string> _listOfStrings;
[Authorize]
public ActionResult ToView1()
{
_listOfStrings = new List<String>(){"test","test2"};
var model = new Model();
return View(model);
}
[Authorize]
public ActionResult FromView1ToView2()
{
var model = new Model(_listOfStrings);
//the issue at hand is that '_listOfStrings' is not persisted.
return View(model);
}
Anyone got an idea if this is possible? (The list is big, so i would prefer not sending it through the model into the view and vice versa)
You need to read about an ASP.NET MVC lifecycle.
Short answer: no, you can't cause Controller is destroyed after a call of an action. Detail answer: you can store (cache) data in a TempData or in a Session properties.
_listOfStrings is a different variable to listOfStrings. You are not writing to or reading from the static field. In the code you have presented, _listOfStrings is not even defined.
Use one static variable and this code will work.

Get controller name in asp.net mvc

In my app I am creating a dynamic menu. The menu is populated depending upon the controller it is called for. For example in one of my Controller name is Organization. To populate the menu for it I call this
#Html.Action("Menu","Site", new { calledForController = "Organization", oId = #Model.Id })
Everything is working nice and smooth but the issue I am experiencing as I am having more views is that I have to put the above line in every view. What I am looking for is a way to get the current controller and action name from the route data so that I don't have to call this on every view.
The ideal solution would be to write something like this
#Html.Action("Menu","Site")
in my _Layout.cshtml and then in the menu controller populate menu list depending upon where it was called from.
If I write
this.ControllerContext.RouteData.Values["controller"].ToString();
in my Menu action of Site controller I am always getting Site as my controller name. Any thoughts on this?
I have searched and found this as an appropriate solution for me, to get the Route data use this
var routeValues = HttpContext.Request.RequestContext.RouteData.Values;
if (routeValues.ContainsKey("id"))
oId = (String)routeValues["id"];
This way in my _Layout.cshtml I can write this
#Html.Action("Menu","Site")
And now I don't have to pass in extra called for controller again and again.

Altering database based on user id

I really looked, googled, this site, for a few days now, tried a bunch of different things, and I can't find an answer.
so, I'm trying to create a web application that will display client information after purchase. I'm using VS2012 express and C#, and I decided to use MVC4, mostly because there was a tutorial on ASP.NET that came pretty close to what I was looking to do. Any comments on my choices is not requested but also not unwelcome.
So the admin will enter all sales information at the end of each day. We record client phone numbers as account numbers in our sales protocol, so my thought was, to keep it simple, to just use the clients phone number as a login to the web application as well. Also, that way, when a client logs into the site to view the database, the database would filter automatically so that the particular client could only see their transactions.
The tutorial I followed is here.
I figured out that this is the point where the filter needs to be applied, but i'm having a lot of trouble doing so.
The controller is named "MainController"
The database is named "Main", table is "Mains"
"AccountNumber" is the field in the db that should match the Current User Id
public ActionResult Index()
{
return View(db.Mains.ToList());
}
As I understand it, I have to place [InitializeSimpleMembership] above, then grab the UserId, then define it as the filter.
First of all, you should decide one of these way:
1) keeping login and user info in a separate table and let the SimpleMembership(SM) does its default jobs.
2) Using an existing table so store users info and tell the SM which table is for.
Approach One:
To handle this approach, all you need is that you create users manually(as you do, I think) and add an extra line to the action method which is responsible of creating customers:
[HttpPost]
public ActionResult Create(Customer model)
{
if (ModelState.IsValid)
{
db.Customers.Add(model);
try
{
db.SaveChanges();
// here it is ...
WebSecurity.CreateUserAndAccount(model.Phone, model.Password);
}
catch
{
insertError = true;
}
// .. Other codes ...
}
Now, your customers can simply login to the site with their phone no. as username and that password.
And to retrieve items related to a specific user - which is currently logged into site - simply use the following query:
public ActionResult Index()
{
return View(db.Mains.Where(m => m.AccountNumber == User.Identity.Name)
.ToList());
}
If you also need approach two, tell me to update my answer and put it here

MVC Razor Hidden input and passing values

I am pretty sure I am doing something wrong here. I have been developing a web app using MVC and Razor and I never thought of using the form element. Now so much has already been done with master pages and sub pages that it means restructuring most of our code in order to use form element and the would result in multiple form elements on a page.
That aside, in Asp.Net if I wanted to access any control in the C# code behind I could just give it an ID="SomeID" and a RUNAT="SERVER". Then in my code behind I could set its value and properties.
When I do this in Razor, I use lines like:
<input id="hiddenPostBack" runat="server" type="hidden" />
Why can't I access this in the controller? I want to detect a postback and set the value to false if it is the first time the page loads, and if not, then set the value to true. Then based on this, I will read it either server side or client side and do something.
My real question is, how do I "do something" both server side and client side given that I don't have a form element. I was under the impression that if I wanted to pass values from client to server and back, the easiest way to do this is with a hidden input. But I am just not getting how to accomplish this with MVC3 and razor.
A move from WebForms to MVC requires a complete sea-change in logic and brain processes. You're no longer interacting with the 'form' both server-side and client-side (and in fact even with WebForms you weren't interacting client-side). You've probably just mixed up a bit of thinking there, in that with WebForms and RUNAT="SERVER" you were merely interacting with the building of the Web page.
MVC is somewhat similar in that you have server-side code in constructing the model (the data you need to build what your user will see), but once you have built the HTML you need to appreciate that the link between the server and the user no longer exists. They have a page of HTML, that's it.
So the HTML you are building is read-only. You pass the model through to the Razor page, which will build HTML appropriate to that model.
If you want to have a hidden element which sets true or false depending on whether this is the first view or not you need a bool in your model, and set it to True in the Action if it's in response to a follow up. This could be done by having different actions depending on whether the request is [HttpGet] or [HttpPost] (if that's appropriate for how you set up your form: a GET request for the first visit and a POST request if submitting a form).
Alternatively the model could be set to True when it's created (which will be the first time you visit the page), but after you check the value as being True or False (since a bool defaults to False when it's instantiated). Then using:
#Html.HiddenFor(x => x.HiddenPostBack)
in your form, which will put a hidden True. When the form is posted back to your server the model will now have that value set to True.
It's hard to give much more advice than that as your question isn't specific as to why you want to do this. It's perhaps vital that you read a good book on moving to MVC from WebForms, such as Steve Sanderson's Pro ASP.NET MVC.
If you are using Razor, you cannot access the field directly, but you can manage its value.
The idea is that the first Microsoft approach drive the developers away from Web Development and make it easy for Desktop programmers (for example) to make web applications.
Meanwhile, the web developers, did not understand this tricky strange way of ASP.NET.
Actually this hidden input is rendered on client-side, and the ASP has no access to it (it never had). However, in time you will see its a piratical way and you may rely on it, when you get use with it. The web development differs from the Desktop or Mobile.
The model is your logical unit, and the hidden field (and the whole view page) is just a representative view of the data. So you can dedicate your work on the application or domain logic and the view simply just serves it to the consumer - which means you need no detailed access and "brainstorming" functionality in the view.
The controller actually does work you need for manage the hidden or general setup. The model serves specific logical unit properties and functionality and the view just renders it to the end user, simply said. Read more about MVC.
Model
public class MyClassModel
{
public int Id { get; set; }
public string Name { get; set; }
public string MyPropertyForHidden { get; set; }
}
This is the controller aciton
public ActionResult MyPageView()
{
MyClassModel model = new MyClassModel(); // Single entity, strongly-typed
// IList model = new List<MyClassModel>(); // or List, strongly-typed
// ViewBag.MyHiddenInputValue = "Something to pass"; // ...or using ViewBag
return View(model);
}
The view is below
//This will make a Model property of the View to be of MyClassModel
#model MyNamespace.Models.MyClassModel // strongly-typed view
// #model IList<MyNamespace.Models.MyClassModel> // list, strongly-typed view
// ... Some Other Code ...
#using(Html.BeginForm()) // Creates <form>
{
// Renders hidden field for your model property (strongly-typed)
// The field rendered to server your model property (Address, Phone, etc.)
Html.HiddenFor(model => Model.MyPropertyForHidden);
// For list you may use foreach on Model
// foreach(var item in Model) or foreach(MyClassModel item in Model)
}
// ... Some Other Code ...
The view with ViewBag:
// ... Some Other Code ...
#using(Html.BeginForm()) // Creates <form>
{
Html.Hidden(
"HiddenName",
ViewBag.MyHiddenInputValue,
new { #class = "hiddencss", maxlength = 255 /*, etc... */ }
);
}
// ... Some Other Code ...
We are using Html Helper to render the Hidden field or we could write it by hand - <input name=".." id=".." value="ViewBag.MyHiddenInputValue"> also.
The ViewBag is some sort of data carrier to the view. It does not restrict you with model - you can place whatever you like.
As you may have already figured, Asp.Net MVC is a different paradigm than Asp.Net (webforms). Accessing form elements between the server and client take a different approach in Asp.Net MVC.
You can google more reading material on this on the web. For now, I would suggest using Ajax to get or post data to the server. You can still employ input type="hidden", but initialize it with a value from the ViewData or for Razor, ViewBag.
For example, your controller may look like this:
public ActionResult Index()
{
ViewBag.MyInitialValue = true;
return View();
}
In your view, you can have an input elemet that is initialized by the value in your ViewBag:
<input type="hidden" name="myHiddenInput" id="myHiddenInput" value="#ViewBag.MyInitialValue" />
Then you can pass data between the client and server via ajax. For example, using jQuery:
$.get('GetMyNewValue?oldValue=' + $('#myHiddenInput').val(), function (e) {
// blah
});
You can alternatively use $.ajax, $.getJSON, $.post depending on your requirement.
First of all ASP.NET MVC does not work the same way WebForms does. You don't have the whole runat="server" thing. MVC does not offer the abstraction layer that WebForms offered. Probabaly you should try to understand what controllers and actions are and then you should look at model binding. Any beginner level tutorial about MVC shows how you can pass data between the client and the server.
You are doing it wrong since you try to map WebForms in the MVC application.
There are no server side controlls in MVC. Only the View and the
Controller on the back-end. You send the data from server to the client by
means of initialization of the View with your model.
This is happening on the HTTP GET request to your resource.
[HttpGet]
public ActionResult Home()
{
var model = new HomeModel { Greeatings = "Hi" };
return View(model);
}
You send data from client to server by means of posting data to
server. To make that happen, you create a form inside your view and
[HttpPost] handler in your controller.
// View
#using (Html.BeginForm()) {
#Html.TextBoxFor(m => m.Name)
#Html.TextBoxFor(m => m.Password)
}
// Controller
[HttpPost]
public ActionResult Home(LoginModel model)
{
// do auth.. and stuff
return Redirect();
}

MVC C# - Simplest Possible Implementation

My first try of MVC. Am trying to implement a simple example. Inspiration from here. Have I got this pattern (yet!)?
View: "Hey, controller, the user just told me he wants the first person"
Controller: "Hmm, having checked his credentials, he is allowed to do that... Hey, model, I want you to get me the first person"
Model: "First person... got it. Back to you, Controller."
Controller: "Here, I'll collect the new set of data. Back to you, view."
View: "Cool, I'll show the first person to the user now."
View:
namespace WinFormMVC
{
public partial class Form1 : Form
{
controller cont = new controller();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
textBox1.Text = cont.checkPermissionsAndGetFirstPerson();
}
}
}
Controller:
public class controller
{
public string checkPermissionsAndGetFirstPerson()
{
string returnValue = "";
if (checkPermissions())
{
model m = new model();
returnValue = m.getFirstPerson();
}
return returnValue;
}
public bool checkPermissions()
{
return true;
}
}
Model:
public class model
{
public string getFirstPerson()
{
return "Bill Smith";
}
}
Hmm... I am not sure if I'd call this MVC... As with ASP.NET WebForm, this form is more like an MVP pattern.
As per my understanding, in MVC, controller is the one responsible for managing all resources and flow of the code. In your example, you basically creating a Windows Form first (the view) and then attach a controller to it which is more of a MVP sort of things.
In a classical MVC pattern, the Model, once instantiated, will be linked to the View and when the model changes, the view will get notified (possibly through Observer / PubSub pattern).
Button click, etc. from the View will be routed to the controller which will coordinate those sort of stuffs.
see: this.
I would describe MVC more like this:
Request (MVC url routing, some event passed from previous UI etc)
Controller - check credentials, get data, return Model
Model - represents the data passed back from the Controller
View - render the Model returned by the Controller. Depending on the Model may display UI to initialise new Controller actions. May also pass Model back to next Controller action.
I think it can be a little confused because in many Model implementations (such as Linq) they provide data definition and access, but it's still the Controller that knows where to start (even if it's the Model that knows how to save its own changes).
So, your code should be something like:
//Controller:
public class PersonController
{
public PersonAction Detail(int personId)
{
Person returnValue;
//get person from DB and populate returnValue
return new PersonAction( returnValue );
}
}
//Model:
public class Person
{
public string FirstName {get; set;}
public string LastName {get; set;}
}
//View:
public partial class PersonDetailView : MVCForm<Person>
{
public Form1( Person model ):base(model) {
textBox1.Text = model.FirstName + " " + model.LastName;
}
private void button1_Click(object sender, EventArgs e)
{
textBox1.Text = model.FirstName + " " + model.LastName;
}
}
What this example is missing is the framework that makes this all possible - there are two significant parts to that:
Something that takes/parses parameters and based on that calls a controller's action method. For instance in Asp.net MVC this is the routing handlers - the call above would be the request url: ~/Person/Detail/personId
Something that takes the result from the action (PersonAction in the example above) and finds the correct view to display. In this example it would open a PersonDetailView form and pass the Person model to it.
There are lots of example frameworks for an MVC implementation for WinForms - one of them may be a good starting point.
To adopt the MVC pattern you want to implement the following:
The view hooks up to the Model and listens for changes.
The controller hooks up to the view and handles specific events i.e. button presses etc
The model processes requests made by the controller and notifies the view.
I agree with Jimmy you would want to integrate something like the Observer pattern to this type of system so its possible for the Model to inform the View when it changes so the View can then update itself accordingly.
The difference with MVP is it introduces a Presenter class which monitors the Model on behalf of the View, in other words the View doesn't know about the Model, it only knows about its Presenter. The Presenter responds to changes in the Model and updates the View accordingly.
I think there are a few corrections to be made to your narrative. Strinctly speaking the view does not contact the controller, the user contacts the controller directly. In a web app it looks like this.
User: Hey web app, can I have the resource at /people/1
Routing engine: That means you person controller. get the first user.
User controller: Model, I need you to get me user record for the authenticated user, and the person record for the first person.
User Controller: Right. I know the authenticated user is an admin, and person one does exist. So return the Admin view for person to the user.
Rendering engine: Build up the html from the view (template) and person object (data)
This is difficult to do in webforms. I guess the best way is to have a page for each controller, and have that page dynamiclly choose and display a user control. One for each view. It is important in MVC that the view is dumb. All requests are handled directly by controllers, which then select which view to use.
Your checkPermissionsAndGetFirstPerson method is probably doing too much. Authorization and fetching data should probably be separate operations.
Also, if your Form1 class is your view, it probably shouldn't be constructing the controller. That seems backwards.
Most information you'll find on MVC in .NET will be for ASP.NET MVC web applications. You might want to check out the WinFormsMVC project on CodePlex to see how someone else has tackled this problem.
http://winformsmvc.codeplex.com/
Here's another WinForms MVC implementation on CodePlex. Looks like it's got a bit more documentation.
http://koosserymvcwin.codeplex.com/
You might find this tutorial very helpful: http://nerddinnerbook.s3.amazonaws.com/Intro.htm. Written by Scott Guthrie, it explains the MVC workflow very well. Part 4 should have the basics you're looking for.

Categories

Resources