I need to know how to pass data between two controllers in asp.net mvc 3
i have two controllers
public class controller1:Controller
{
}
public class controller2:Controller
{
}
how to pass data from controller1 to controller2?
One way is to pass using TempData:
public class controller1Controller:Controller
{
public ActionResult Index()
{
TempData["SomeKey"] = "Some Value";
return RedirectToAction("Index","controller2");
}
}
public class controller2Controller:Controller
{
public ActionResult Index()
{
string value = TempData["SomeKey"] as String;
return View();
}
}
One thing to remember is TempData is single read, which means that once a value is read from TempData it will automatically be deleted, if the value is till needed after read and you want to persist it, you have to call TempData.Keep() and you can be more specific to persist specific key value by calling:
string value = TempData["SomeKey"] as String;
TempData.Keep("SomeKey");
Another way is to use RouteValue Dictionary:
public class controller1Controller:Controller
{
public ActionResult Index()
{
return RedirectToAction("Index","controller2",new { SomeKey = "SomeValue"});
}
}
public class controller2Controller:Controller
{
public ActionResult Index(string SomeKey)
{
return View();
}
}
I am using String in example, you can have a custom type like a model or view model object that is to be passed.
I would suggest you to read this MSDN article for more details and understanding of passing data in mvc application.
You should also read What is ViewData, ViewBag and TempData? – MVC options for passing data between current and subsequent request and When to use ViewBag, ViewData, or TempData in ASP.NET MVC 3 applications
You can use RouteValue Dictionary here as :-
public class controller1Controller:Controller
{
public ActionResult Index()
{
return RedirectToAction("Index","controller2",new { UserName= "Username"}); <----Just pass username value here
}
}
public class controller2Controller:Controller
{
public ActionResult Index(string UserName) <-----get username value here
{
return View();
}
}
Related
I want to know, there is any technique so we can pass Model as a parameter in RedirectToAction
For Example:
public class Student{
public int Id{get;set;}
public string Name{get;set;}
}
Controller
public class StudentController : Controller
{
public ActionResult FillStudent()
{
return View();
}
[HttpPost]
public ActionResult FillStudent(Student student1)
{
return RedirectToAction("GetStudent","Student",new{student=student1});
}
public ActionResult GetStudent(Student student)
{
return View();
}
}
My Question - Can I pass student model in RedirectToAction?
Using TempData
Represents a set of data that persists only from one request to the
next
[HttpPost]
public ActionResult FillStudent(Student student1)
{
TempData["student"]= new Student();
return RedirectToAction("GetStudent","Student");
}
[HttpGet]
public ActionResult GetStudent(Student passedStd)
{
Student std=(Student)TempData["student"];
return View();
}
Alternative way
Pass the data using Query string
return RedirectToAction("GetStudent","Student", new {Name="John", Class="clsz"});
This will generate a GET Request like Student/GetStudent?Name=John & Class=clsz
Ensure the method you want to redirect to is decorated with [HttpGet] as
the above RedirectToAction will issue GET Request with http status
code 302 Found (common way of performing url redirect)
Just call the action no need for redirect to action or the new keyword for model.
[HttpPost]
public ActionResult FillStudent(Student student1)
{
return GetStudent(student1); //this will also work
}
public ActionResult GetStudent(Student student)
{
return View(student);
}
Yes you can pass the model that you have shown using
return RedirectToAction("GetStudent", "Student", student1 );
assuming student1 is an instance of Student
which will generate the following url (assuming your using the default routes and the value of student1 are ID=4 and Name="Amit")
.../Student/GetStudent/4?Name=Amit
Internally the RedirectToAction() method builds a RouteValueDictionary by using the .ToString() value of each property in the model. However, binding will only work if all the properties in the model are simple properties and it fails if any properties are complex objects or collections because the method does not use recursion. If for example, Student contained a property List<string> Subjects, then that property would result in a query string value of
....&Subjects=System.Collections.Generic.List'1[System.String]
and binding would fail and that property would be null
[HttpPost]
public async Task<ActionResult> Capture(string imageData)
{
if (imageData.Length > 0)
{
var imageBytes = Convert.FromBase64String(imageData);
using (var stream = new MemoryStream(imageBytes))
{
var result = (JsonResult)await IdentifyFace(stream);
var serializer = new JavaScriptSerializer();
var faceRecon = serializer.Deserialize<FaceIdentity>(serializer.Serialize(result.Data));
if (faceRecon.Success) return RedirectToAction("Index", "Auth", new { param = serializer.Serialize(result.Data) });
}
}
return Json(new { success = false, responseText = "Der opstod en fejl - Intet billede, manglede data." }, JsonRequestBehavior.AllowGet);
}
// GET: Auth
[HttpGet]
public ActionResult Index(string param)
{
var serializer = new JavaScriptSerializer();
var faceRecon = serializer.Deserialize<FaceIdentity>(param);
return View(faceRecon);
}
[NonAction]
private ActionResult CRUD(someModel entity)
{
try
{
//you business logic here
return View(entity);
}
catch (Exception exp)
{
ModelState.AddModelError("", exp.InnerException.Message);
Response.StatusCode = 350;
return someerrohandilingactionresult(entity, actionType);
}
//Retrun appropriate message or redirect to proper action
return RedirectToAction("Index");
}
i did find something like this, helps get rid of hardcoded tempdata tags
public class AccountController : Controller
{
[HttpGet]
public ActionResult Index(IndexPresentationModel model)
{
return View(model);
}
[HttpPost]
public ActionResult Save(SaveUpdateModel model)
{
// save the information
var presentationModel = new IndexPresentationModel();
presentationModel.Message = model.Message;
return this.RedirectToAction(c => c.Index(presentationModel));
}
}
I work with asp MVC 4. I have a single controller and I want to share the same object between his functions. I thought about a data member but it doesn't work. Here is my code :
public class MyController : Controller
{
public MyObject obj;
public ActionResult Index()
{
obj = new MyObject();
this.obj.GetData(); // Fill my object
return View();
}
public ActionResult MyFunction()
{
Console.Write(this.obj); // Always null
return View();
}
}
Is it possible to keep this object between functions ? I used to create TempData ou ViewBags for sharing data but I'm not sure if it's the right way to manage big objects.
It is null because MVC framework create a new controller to handle different requests, hence the obj is also different.
If you make your Object singleton or simply make it static, it will work.
public static MyObject obj;
Try this:
public class MyController : Controller
{
public MyObject obj = new MyObject();
public ActionResult Index()
{
this.obj.GetData(); // Fill my object
return View();
}
public ActionResult MyFunction()
{
Console.Write(this.obj); // Always null
return View();
}
}
This will stop your null error.
If you want to save data between postbacks, you will need to look into persistent data storage such as a SQL based database.
I can't seem to get the edit function of my view to work..i have a page that lists, a page that shows specific detail and on that page, i should be able to edit the information of the form..PROBLEM: when i run the application it says:No parameterless constructor defined for this object. What am i doing wrong...?
In the Home Controller i have:
Edit Functions:
[HttpGet]
public ViewResult EditSchoolDetails(int id)
{
var institution = _educationRepository.GetInstititionById(id);
var model = (Mapper.Map<Institution, InstitutionModel>(institution));
return View(model);
}
post
[HttpPost]
public ActionResult EditSchoolDetails( InstitutionModel institutionModel, int id)
{
if (ModelState.IsValid) {
//_get from repository and add to instituion
var institution = _educationRepository.GetInstititionById(institutionModel.Id);
// Map from the view model back to the domain model
var model = Mapper.Map<Institution, InstitutionModel>(institution);
//UpdateModel(model);
SaveChanges();
return RedirectToAction("ViewSchoolDetails", new {institutionModel = institutionModel, id = id});
}
return View(institutionModel);
}
InstitutionModel
public class InstitutionModel {
public InstitutionModel() {
NAABAccreditations = new List<AccreditationModel>();
}
public int Id { get; set; }
public string Name { get; set; }
public bool IsNAAB { get { return NAABAccreditations.Any(); } }
public string Website { get; set; }
public AddressModel Address { get; set; }
public IEnumerable<AccreditationModel> NAABAccreditations { get; set; }
}
Does the Institution class have a parameterless constructor? If not, that will be the problem. You are passing an InstitutionModel to the the edit view, so the post action should probably take an InstitutionModel too, then you can map back to the original Institution model:
public ActionResult EditSchoolDetails(int id, InstitutionModel institutionModel)
{
if (ModelState.IsValid)
{
//add to database and save changes
Institution institutionEntity = _educationRepository.GetInstititionById(institution.Id);
// Map from the view model back to the domain model
Mapper.Map<InstitutionModel, Institution>(institutionModel, institutionEntity);
SaveChanges();
return RedirectToAction("ViewSchoolDetails",);
}
return View(institutionModel);
}
Notice also how it returns the view model back to the view if the model state isn't valid, otherwise you will lose all your form values!
Here's a similar question too which might help: ASP.NET MVC: No parameterless constructor defined for this object
Is it possible you need to pass a parameter to ViewSchoolDetails? I notice in the return statement you commented out that you were passing it an id, but in the return statement you're using, you're not passing in anything.
EDIT
This (from your comment below):
parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult ViewSchoolDetails(Int32)
...tells me you need to pass a parameter to ViewSchoolDetails
EDIT 2
I saw your edit, and would say this: if the method you are calling is
public ActionResult ViewSchoolDetails(InstitutionModel institutionModel, int id)
Then you MUST pass it an object of type InstitutionModel and an int as parameters or you will get an exception. Meaning, you need
RedirectToAction("ViewSchoolDetails", new {institutionModel = institutionModel, id = id});
Whenever i get this, i have forgotten to create a parameter-less constructor on my view-model. I always add one now just in case it's needed and i forget.
Does InstitutionModel have one?
public class SomeViewModel
{
public List<Something> listOfSomethings = new List<Something>();
public Entity EntityObj;
etc...
etc..
..
}
public class Controller()
{
public SomeViewModel viewModel;
public ActionResult SomeAction()
{
viewModel = populateViewModel();
return View(viewModel);
}
}
The SomeViewModel is a large object that is populated in the controller's action. Will it be GC'd or cleared from memory when the controller is disposed?
There is no point of this public SomeViewModel viewModel; field in your controller. Controller actions are independant meaning that if you first invoke SomeAction which sets a value for this field and then invoke some other action do not expect this field to survive. So you should simply use this:
public class HomeController: Controller
{
public ActionResult SomeAction()
{
var viewModel = populateViewModel();
return View(viewModel);
}
public ActionResult SomeOtherAction()
{
var viewModel = populateViewModel();
return View(viewModel);
}
}
This being said your current code doesn't seem to have memory leaks because once the request ends the Controller class will be eligible for GC and so all its instance fields including the view model.
if populateViewModel method does not use disaposable resources (as data context) or uses and disposes them, your code should be fine.
Image the following controller method:
public ActionResult ShipmentDetails(Order order)
{
return View(new OrderViewModel { Order = order });
}
The incoming order parameter is filled from a custom model binder, that either creates a new order for this session and stores it in the session, or reuses an existing order from the current session. This order instace is now used to fill a shipment details form, where users can enter their address and so on.
When using #using(Html.BeginForm()) in the view. I cannot use the same signature for the post method again (because this would result in ambigious method names) and I found me adding a dummy parameter just to make this work.
[HttpPost]
public ActionResult ShipmentDetails(Order order, object dummy)
{
if (!ModelState.IsValid)
return RedirectToAction("ShipmentDetails");
return RedirectToAction("Initialize", order.PaymentProcessorTyped + "Checkout");
}
What are the best practices for this? Would you simply rename the method to something like PostShipmentDetails() and use one of the overloads of BeginForm? Or does the problem originate from the point, that the first method has the order parameter?
You could use the ActionName attribuite:
[HttpPost]
[ActionName("ShipmentDetails")]
public ActionResult UpdateShipmentDetails(Order order) { ... }
or a more classic pattern:
public ActionResult ShipmentDetails(int orderId)
{
var order = Repository.GetOrder(orderId);
return View(new OrderViewModel { Order = order });
}
[HttpPost]
public ActionResult ShipmentDetails(Order order)
{
if (!ModelState.IsValid)
return RedirectToAction("ShipmentDetails");
return RedirectToAction("Initialize", order.PaymentProcessorTyped + "Checkout");
}