I have two action methods inside a controller. With the help of first action method, I am fetching the required data from database and I need to get this fetched data inside the second action method. I need to achieve this without passing any parameter to the second method. I don’t know how to do this as I am new to MVC.
Method 1:
public ActionResult GetData(HttpPostedFileBase file)
{
string folderPath = Server.MapPath(ConfigurationManager.AppSettings["BackupPath"]);
List<string> invalidRecords = new List<string>();
string backupFileName = FileUpload.BackupFile(file, folderPath);
invalidRecords = File.GetDataFromDB(backupFileName);
List<DataVM> lst = serviceData.GetAllData();
return View(lst);
}
Method 2:
[HttpPost]
public JsonResult GetInvalidRecords()
{
List<string> InvalidVehicleId = InvalidRecords;
return new JsonResult { Data = InvalidRecords };
}
You can use a session variable to hold the value of your 'lst' variable in your 'GetData' action:
Session["data"] = lst
Then you can retrieve it as follows and cast it to the appropriate type:
var data = (List<DataVM>)Session["data"]
https://msdn.microsoft.com/en-us/library/ms178581.aspx
You can use TempData as well
TempData["Name of Tempdata variable "]= File.GetDataFromDB(backupFileName)
and in other action you can recieve it
var getdatafromanotherAction= TempData["Name of Tempdata variable"]
If you want to call both action methods in single call, You can use
return RedirectToAction("GetInvalidRecords") in the first method. Also, you can create a class level private variable _listdata. Set it in first method , get in second method.
If you want to keep data between the 2 calls, use Tempdata.Keep and Tempdata.Peek but you need to make sure that call for second method immediately follows first method. Tempdata works between 2 requests only unless you extend its duration by using .Keep and .Peek once more.
If these two methods are to be called few calls apart, you can use session variable to keep the data.
Alternatively, you can keep the parameter of the second method call optional. So, it won't hurt other calls of the jsonresult method. Inside the method, you can check whether parameter is empty or not.
Related
I'm trying to make a service to AB-test different views on a page. The service has a method that takes a variable amount of ViewResults and returns one of them after determining which version to serve. The problem is that the model applied to the last ViewResult in the arguments list is applied to all arguments. The below code is a simplified version of my code just to illustrate the setup:
This is the method in the service:
public ViewResult GetTestVariantView(params ViewResult[] views){
...omitted randomization code that returns an index
return views[index] ?? views[0]
}
This is how it's used in the controller:
public ActionResult Index(){
var modelOne = new PageViewModel(letter: "A");
var modelTwo = new PageViewModel(letter: "B");
var modelThree = new PageViewModel(letter: "C");
return _testingService.GetTestVariantView(
View("~/Views/_PageView.cshtml", modelOne),
View("~/Views/_SomeOtherPageView.cshtml", modelTwo ),
View("~/Views/_PageView.cshtml", modelThree));
}
I expect to get for example _PageView.cshtml with modelOne if the service returns index 0 of the params list - but no, I get _PageView.cshtml with modelThree. Somehow just the model is taken from the last entry though, because if the service returns index 1 I get _SomeOtherPageView.cshtml with modelThree.
I can't find any documentation or similar questions asked about how to resolve this or even do it in another way. Is there a more proper way to determine which view to present using an external method? I know I could return an index from the method and have a switch/ifelse statement in the controller but I'd like to avoid that if possible simply because it clutters the controller.
What are my options?
Looking at the source code, the model passed to the View method is stored in the ViewData collection, not the returned ViewResult. If you call View multiple times with different non-null models, you will overwrite the ViewData.Model property each time, and only the last value will be used.
As Camilo said, change your code so that you only call View once. For example:
public (string viewName, object model) GetTestVariantView(
params (string viewName, object model)[] views)
{
...
}
(string viewName, object model) = _testingService.GetTestVariantView(
("~/Views/_PageView.cshtml", modelOne),
("~/Views/_SomeOtherPageView.cshtml", modelTwo ),
("~/Views/_PageView.cshtml", modelThree));
return View(viewName, model);
I have a method defined like this:
public ActionResult MatchedBusinesses(List<Business> businesses)
{
if (businesses != null)
{
return View(businesses);
}
return View("NoMatchFound");
}
Then, in my other method I have something similar to this one:
var list = results.AsEnumerable().OrderBy(b => Math.Abs(Convert.ToInt32(temp) - Convert.ToInt32(b.Zip))).Take(5).ToList();
return RedirectToAction("MatchedBusinesses", "Home", list);
The point is that, for the list variable I get the 5 entries that I select using the query. But, then I want to pass that result to my other method, which will be used in other method's view. The problem is, when I call the other method, the businesses parameter is always null. How can I solve the problem? Clearly, I'm not passing the parameter to my MatchedBusinesses method correctly. Any idea, how to solve the problem?
You are using the overload of RedirectToAction where the 3rd parameter is object routeValues. Internally the method uses reflection to build the route values based on the names and the ToString() values of the objects properties.
It works only for properties that are value types, but for properties that are complex types, including collections, it will not bind because (in your case) the value is a string "List<YourAssembly.Business>" and a string cannot be bound to a collection.
You need to persist the collection before redirecting (e.g. database, session, TempData) and then retrieve the collection in the action result.
For example
var list = results.AsEnumerable()....
TempData["results"] = list;
return RedirectToAction("MatchedBusinesses", "Home");
public ActionResult MatchedBusinesses()
{
List<Business> businesses = (List<Business>)TempData["results"];
}
but use TempData with caution (if the user refreshes the browser, the data will be lost). Its better to persist the information to the database with some key, and then pass the key as a route parameter to the MatchedBusinesses() method so that you can retrieve the data from the database.
Edit
What you're trying to do doesn't make much sense. You cannot, and should not, attempt to send large and/or complex objects, like a List, using Route. Instead you should use POST, or follow Stephen Muecke's suggestion in using TempData
However, here's how you can correctly send simple values using RouteValue
You pass parameters by using
return RedirectToAction("ActionName", "ControllerName",
new { paramName = paramValue });
Or if the target Action it's in the same controller
return RedirectToAction("ActionName", new { paramName = paramValue });
The parameter name, is optional. But using
return RedirectToAction("ActionName", new { paramName = paramValue });
Implies that the target action accepts a parameter with the name paramValue.
Here are all the overloads for RedirectToAction
http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.redirecttoaction%28v=vs.118%29.aspx
Try wrapping your parameter in your return statement in a blank object variable like so:
return RedirectToAction("MatchedBusinesses", "Home", new { businesses = list });
All of the route values for an action have to be one parameter, so it's passed as an object, and then split into the various parameters of the receiving action. Even if you have only one param, it's still looking for an object to split.
I am using a few methods and interfaces in this one. What i need is for the method I'm making to just simply remove 1 value in an array of attributes. All of the stuff here was previously created by someone else, and I'm just creating the removal part for the attribute to be removed. At any rate, the method that does the profile attribute work and sets the value does some work on the back end. I have a method for a UserProfileAttributeSetRequest that looks like this:
public UserProfileAttributeSetRequest()
{
}
public UserProfileAttributeSetRequest(Guid userIdentifier, Dictionary<string, string> profileAttributes)
{
UserIdentifier = userIdentifier;
ProfileAttributes = profileAttributes;
}
This fires a method on the back end that will take in the information being passed to it and change whatever needs to be changed. The method I'm building in the controller probably needs some work, I'm still fairly new to MVC, but here's what I've got:
public ActionResult RemoveEmployeeID(UserInfo userInfo)
{
User usr = UserManager.GetUser(userInfo.UserGuid);
var empID = usr.ProfileAttributes.FirstOrDefault(e => e.ProfileAttributeID == 3);
usr.ProfileAttributes.Remove(empID);
UserProfileAttributeSetRequest upd = new UserProfileAttributeSetRequest();
}
I'm grabbing the complete user, and isolating the single attribute I want to be changed, but the Request complains when I put any parameters in it. What am I doing wrong?
try like this
var emp = usr.ProfileAttributes.Where(e => e.ProfileAttributeID == 3).FirstOrDefault();
usr.ProfileAttributes.Remove(emp);
you have to update the database after removing the item.
My controller has different methods that use the same result returned by a stored procedure called by a LINQ query,
Is there a way to create a global variable that contains the result after making only one call to the procedure ??
I tried creating a constructor but every time the variable (ListePays) is used a new query is executed
public class BUController : Controller {
private NAV_MAUIEntities db = new NAV_MAUIEntities();
public DbSet<liste_pays> ListePays;
public BUController() {
ListePays = db.liste_pays();
}
public JsonResult BillPh(string Pays) {
var x = from pays in ListePays
where pays.Pays.ToUpper() == Pays.ToUpper()
select pays.code_pays;
string CodePays = x.FirstOrDefault().ToString();
}
public JsonResult BillPh2(string Pays) {
var x = from pays in ListePays
where pays.Pays.ToUpper() == Pays.ToUpper()
select pays.code_pays;
string CodePays = x.FirstOrDefault().ToString();
}
}
If the methods are all called as part the processing of the same HTTP request, just make sure some central actor (say, the action method) calls the procedure and passes the result to each method.
public ActionResult MyAction()
{
var data = db.liste_pays();
Method1(data);
Method2(data);
return View();
}
On the other hand, if you want to share the result across HTTP requests, you can cache the result of the procedure call in a number of locations (this is not an exhaustive list):
In the ASP.NET session
In a static variable
In System.Web.Caching.Cache
Not knowing more about your specific scenario, I can't recommend one over the other. However, be aware that the two latter options will potentially share the data between users, which may or may not be what you want.
NOTE: As your code stands at the moment, the call to db.liste_pays() is inside the constructor of BUController, so it is called every time a controller is created, that is, every time a new incoming HTTP request arrives. In other words, your assumption that it is being called every time the variable is used is not entirely correct.
First of all, there is no need for a constructor into an ASP.NET MVC controller.
What you did, means that every time a user makes a call to this controller, a call will be made to the DB to retrieve all your "pays".
I assume you are using Entity Framework. And the way you use Linq is "LinqToEntities". Do not worry about your DB calls, those are managed by the entity framework.
So, now, you just have to use linq that way :
public JsonResult BillPh(string Pays)
{
string codePays = db.liste_pays.FirstOrDefault(f =>
f.Pays.ToUpper() == Pays.ToUpper())
.CodePays.ToString();
}
And the syntax for the query is called "Lambda expressions".
Good luck ;-)
I am Calling an ASP.NET C# Method (Web Method) Using JavaScript.
C#:
[WebMethod]
public static List<Employee> GetEmployeeList(int DeptID,out int TotalRecordsCount)
{
<Employee> obj = new List<Employee>();
//obj = Geting reocrds from Database
TotalRecordsCount = obj.Count();
return obj;
}
Javascript:
function BindList(){
var DeptID = 10;
var TotalRecordsCount = 0;
PageMethods.GetEmployeeList(DeptID,TotalRecordsCount,onsuccess);
}
Now I am getting errors, while calling above js method. Please suggest me where I done mistake.
My main aim is that, Instead of returning single list, Can I add 2 or more different lists ?
Thanks in adv.
Out methods should contain the out key word when it is called like
PageMethods.GetEmployeeList(DeptID,out TotalRecordsCount, onsuccess);
But out is not a keyword in js. So I don't know if it is possible (I would be surprised). Why not return the out parameter as part of the result. So instead of just a list, a list with another value. Another thing that is unusual in your code is that you are trying to set the out parameter before calling the method.
I have never tried using an out when calling the method in Js and its probably not very good design even if it is allowed.
Also see
Is it unusual for a web service call to have an "out" parameter?