Both TempData[] and static fields can be used to pass data from ActionResult to another.
Is there performance/memory difference? best practice?
I also noticed that when paging or sorting, the Detail function is recalled which lead that the list of cars should remain in memory.
public class TestController
{
private static IEnumerable<Cars> _cars;
public ActionResult Detials()
{
var uploadedCars = TempData["cars"] as IEnumerable<Cars>;
var testViewModel = new TestViewModel();
var result = TestViewModel.Process(uploadedCars);
//var result = TestViewModel.Process(_cars);
return View(result);
}
public ActionResult UploadCars(object obj)
{
// upload file ...
_cars= null; // reset value
//_cars= loader.GetAllCars(uploader);
TempData["cars"] = loader.GetAllCars(uploader);
return RedirectToAction("Detials");
}
}
}
Related
I am using .NET Core and SQLKata to access SQL Server database.
I have a method to get all records from the database using SQLKata.Execution.PaginationResult.
This is in Repository:
public class MyTableRepository : IMyTableRepository
{
private QueryFactory _db;
public MyTableRepository(IConfiguration configuration)
{
var conn = new
SqlConnection(configuration.GetConnectionString("MyTable"));
_db = new QueryFactory(conn, new SqlKata.Compilers.SqlServerCompiler());
}
public PaginationResult<MyModel> GetAll(int page = 0, int perPage = 25)
{
dbResult = _db.Query("MyTable").Paginate<MyModel>(page, perPage);
return dbResult;
}
The above is called from my Controller like so:
private readonly IMyTableRepository _MyTableRepository;
public MyTableController(IMyTableRepository MyTableRepository)
{
_MyTableRepository = MyTableRepository;
}
[HttpGet]
[Route("GetMyTable")]
public List<MyModel> GetMyTable()
{
PaginationResult<MyModel> dbResult = MyTableRepository.GetAll(1,
25);
List<MyModel> AccumResult = dbResult.List.ToList();
while(dbResult.HasNext)
{
dbResult = dbResult.Next();
AccumResult.AddRange(dbResult.List.ToList());
}
return AccumResult;
}
How do I get the Next set of result from dbResult ?
I tried below, after I execute GetMyTable, I execute GetNextMyTable, but in PaginationResult GetNext(), dbResult is always null.
In controller:
[HttpGet]
[Route("GetNextMyTable")]
public List<MyTable> GetNextMyTable()
{
var result = _MyTableRepository.GetNext().List;
return result.ToList();
}
In Repository:
public PaginationResult<MyTable> GetNext()
{
while(dbResult.HasNext) //--->> dbResult is null
{
dbResult = dbResult.Next();
return dbResult;
}
return null;
}
If I do the Next method inside the Controller, I am also getting an error
private readonly IMyTableRepository _MyTableRepository;
private PaginationResult<SP_SMA_Reporting_Accts> dbResult;
[HttpGet]
[Route("GetMyTable")]
public List<MyModel> GetMyTable()
{
var dbResult = _MyTableRepository.GetAll(1, 25).List;
return dbResult.ToList();
}
[HttpGet]
[Route("GetNextMyTable")]
public List<MyTable> GetNextMyTable()
{
var result = dbResult.Next().List;//->Error since dbResult is null
return result.ToList();
}
In short refactor your repository method GetAll to call the db.Query
use:
_db.Query("MyTable").Paginate<MyModel>(page, perPage);
instead of
_db.Paginate<MyModel>(new Query("MyTable"), page, perPage);
Explanation:
when calling the Next() method the PaginationResult delegate the pagination process to the holding query, in your case since your are passing new Query() thus no connection info, you are getting null.
I want to use the list of state controller in a district controller. Are there any better ideas.
I have tried one which is working
I put this code in the district controller by using constructor injection.
In this case, the entire code needs to be placed in the district controller.
Is there any way to reduce the code. A better way?
#region StateDropDown
public List<SelectListItem> StateDropDown()
{
List<SelectListItem> selectListItem = new List<SelectListItem>();
List<StateViewModel> stateList = Mapper.Map<List<State>, List<StateViewModel>>(_stateBusiness.GetStateForSelectList());
if (stateList != null)
foreach (StateViewModel state in stateList)
{
selectListItem.Add(new SelectListItem
{
Text = state.Description,
Value = state.Code.ToString(),
Selected = false
});
}
return selectListItem;
}
#endregion StateDropDown
This is what the term 'reusability' is invented for. Place the code in another file and make calls to it from any number of controllers you want, like code below.
//StateBusiness.cs
public class StateBusiness
{
public List<SelectListItem> GetStatesForDropdown()
{
//your logic here
return new List<SelectListItem>();
}
}
//StateController.cs
public class StateController : Controller
{
var state = new StateBusiness();
public ActionResult Index()
{
//call your code here
var states = state.GetStatesForDropdown();
//and do whatever you want
ViewBag.states = states;
return View();
}
}
//DistrictController.cs
public class DistrictController : Controller
{
var state = new StateBusiness();
public ActionResult Index()
{
//call it from here just the same
var states = state.GetStatesForDropdown();
ViewBag.states = states;
return View();
}
}
I don't know about better, but you could shorten this considerably using linq Select.
Mapper.Map<List<State>, List<StateViewModel>>(_stateBusiness.GetStateForSelectList())?
.Select(state => new SelectListItem
{
Text = state.Description,
Value = state.Code.ToString(),
Selected = false
}))?.ToList() ?? List<SelectListItem>();
If you using core one option might be to keep this off the controller and use a TagHelper this will let you inject the options into the tag with a simple attribute state-items reducing controller dependencies and keeping this state off the ViewBag while being more reusable.
Here is how it wold look in the view:
<select asp-for="State" state-items />
The TagHelper:
[HtmlTargetElement("select", Attributes = "state-items")]
public class StateItemsTagHelper : TagHelper {
private readonly StateBusiness _stateBusiness;
[HtmlAttributeName("asp-for")]
public ModelExpression For { get; set; }
public StateItemsTagHelper(StateBusiness stateBusiness) {
this._stateBusiness = stateBusiness;
}
public override void Process(TagHelperContext context, TagHelperOutput output) {
content.TagMode = TagMode.StartTagAndEndTag;
var value = For?.Model as string;
var items = _stateBusiness.GetStateForSelectList()?.Select(state => new SelectListItem {
Text = state.Description,
Value = state.Code.ToString(),
Selected = value == state.Code.ToString()
})) ?? Enumerable.Empty<SelectListItem>();
foreach(var item in items) {
output.Content.AppendHtml(item.ToHtmlContent());
}
}
}
For reusability item.ToHtmlContent is an extension method:
public static IHtmlContent ToHtmlContent(this SelectListItem item) {
var option = new TagBuilder("option");
option.Attributes.Add("value", item.Value);
if(item.Selected) {
option.Attributes.Add("selected", "selected");
}
option.InnerHtml.Append(item.Text);
return option;
}
I am setting the value of TempData in one ActionResult of different controller and trying to get their Keys of just counts in another controller's ActionResult
public ActionResult DealProducts(FormCollection form)
{
TempData["check"] = "DealUpdated";
}
in another controller
public ActionResult CustomizedBudget()
{
var temp = TempData["doc"];
var temp = TempData["doc"].Key;//like this
if (temp.Count > 0) // or trying to get like this, but not
}
To Assign
public ActionResult DealProducts(FormCollection form)
{
TempData["check"] = "DealUpdated";
}
In CSHTML
#{
TempData.Keep("check");
}
in another controller
public ActionResult CustomizedBudget()
{
var count = TempData.Keys.Count;
var DealUpdatedValue = TempData["check"];
}
well since you have
public ActionResult DealProducts(FormCollection form)
{
TempData["check"] = "DealUpdated";
}
shouldn't you have
public ActionResult CustomizedBudget()
{
var temp = TempData["check"];
var temp = TempData["check"].Key;//like this
if (temp.Count > 0) // or trying to get like this, but not
}
?
you need to change in below Action
public ActionResult CustomizedBudget()
{ var temp = TempData["check"]; }
I'm storing list of string in to a session. Then I don't know how to get those data to display in my view.
This is my code:
public List<Details> d = new List<Details>();
[HttpPost]
public void getDatas(string destination)
{
XElement rootele = XElement.Load(Server.MapPath("~/XmlFiles/CruiseData/cruiseprodutstwo.xml"));
var getneededData = rootele.Elements("CruiseProduct")
.Where(l => l.Element("Location").Value == destination)
.Select(s => s.Element("Name").Value);
foreach (var itm in getneededData)
{
d.Add(new Details
{
cruiseName = itm
});
}
Session["names"] = d;
Response.Redirect("Check",true);
}
This is my check action method
public ActionResult Check()
{
var chk = Session["names"];
return View();
}
You can store your data in ViewBag, then retrieve them in view:
public ActionResult Check()
{
ViewBag.SessionData = Session["names"] as List<DetailsList>;
Return View();
}
Then in your view, use simply as
#If (ViewBag["SessionData"]!= null){
// Do jobs with SessionDetails what you want
}
Hope this helps.
Controller
public ActionResult Check()
{
var chk = Session["names"];
List<Details> list = Session["names"] as List<Details>;
ViewBag.MyList = list ;
return View();
}
View
#ViewBag.MyList
// e.g.
#foreach (var item in ViewBag.MyList) { ... }
Firstly, it is better to use ViewBag, ViewData and/or TempData when playing with MVC.
The use is quite simple for all the three. Here are the steps :
You assign them some value/object : ViewBag.SomeField = SomeValue;
You use them on your view side : #ViewBag.SomeField.
Here are some link that will definitely get you through :
ViewBag ViewData and TempData
ViewBag ViewData and TempData Basics
Since you are redirecting to an action method here, I would suggest using TempData for your case and using that in the view.
Hope this helps.
I would like to return an image that is dynamically created instead of retrieving from a database or from file. Let's say I have a simple ZipCode class. I would like to have a property that would return an image representation of the zipcode. The JSON returns "ZipAsImage":"System.Drawing.Bitmap".
Yes I am new to the programming in the web world. Yes I have looked for other examples but they seemed to only return an image. Thanks for any help.
public class ZipCode
{
public int ZipCodeId { get; set; }
[NotMapped]
public Image ZipAsImage
{
get
{
// Create a blank iamge for now to test.
return new Bitmap(50, 50);
}
set { }
}
}
My ApiController class
public class ZipCodesController : ApiController
{
private MyContext db = new MyContext();
// GET api/ZipCodesController
public IEnumerable<ZipCode> GetZipCodes()
{
return db.zipcodes.AsEnumerable();
}
// GET api/ZipCodesController/5
public ZipCode GetZipCode(int id)
{
ZipCode zipcode = db.ZipCodes.Find(id);
if (zipcode == null)
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
return zipcode;
}
...
My Controller class
public class ZipCodesController : Controller
{
private MyContext db = new MyContext();
//
// GET: /ZipCodes/
public ActionResult Index()
{
var zipcodes = db.ZipCodes.Include(z => z.State);
return View(zipcodes.ToList());
}
//
// GET: /ZipCodes/Details/5
public ActionResult Details(int id = 0)
{
ZipCode zipcode = db.ZipCodes.Find(id);
if (zipcode == null)
{
return HttpNotFound();
}
return View(zipcode);
}
...
I dont undersatnd the point where you are showing the MVC Contoller.Am i missing something there? However For Webapi (ApiController) You can re write your Method as follows. This should pass the enitre Object in one response.
public HttpResponseMessage GetZipCode(int id)
{
ZipCode zipcode = db.ZipCodes.Find(id);
if (zipcode == null)
{
return Request.CreateResponse(HttpStatusCode.NotFound)
}
return Request.CreateResponse(HttpStatusCode.OK,zipcode);
}
Sending Binary Images. You need to set Straemcontent and content-type. I found a link that can help you with that Images with Webapi . Look through the entire thread . You might figure out quickly whats missing...