This is a pretty basic question but just want help understanding how a server interacts with the browser/computer connecting to it.
When a user hits the Create() action it sends the Currentclaim object to the view. Because the _currentclaim variable is null it creates a new object with certain properties. If I load up another browser (IE, Safari) and use the app it isn't a 'fresh start' as _currentclaim has retained the properties that were given to it in the other browser.
public class ClaimsController : Controller
{
private static ClaimViewModel _currentclaim;
private static ClaimViewModel Currentclaim
{
get
{//If _currentclaim is null then create it. Return it.
if (_currentclaim == null)
_currentclaim = GetClaimViewModel();
return _currentclaim;
}
set//set value of Currentclaim.
{
_currentclaim = value;
}
}
public static ClaimViewModel GetClaimViewModel()
{
return new ClaimViewModel()
{
ClaimID = 101,
SubmissionUserID = 10,
DateSubmitted = DateTime.Now,
LineViewModels = new List<LineViewModel>() {
new LineViewModel() {MeetingDate=DateTime.Now,SubCatID=1},
}
};
}
public ActionResult Create()
{
return View(Currentclaim);
}
[HttpPost]
public ActionResult Create(ClaimViewModel claimvm)
{ claimvm.SubmissionUserID = Currentclaim.SubmissionUserID;
claimvm.DateSubmitted = Currentclaim.DateSubmitted;
_currentclaim = claimvm;
return View("Summary", Currentclaim);
}
}
I just want to be reasssured that when a user connects to my web application from wherever it is hosted that his or her session will start with a null object (and not one instantiated by someone else .... if that makes sense)
Related
Below is the setup that I am trying to test.
The controller:
public ActionResult UpsertStudent(StudentModel studentModel)
{
try
{
if (!CheckStudentUpdateForEdit(studentModel))
{
return Json(new { result = STUDENT_EXISTS });
}
// remaining code removed for brevity
}
private bool CheckStudentUpdateForEdit(StudentModel studentModel)
{
var returnVal = true;
var existingStudent = _updateStudentManager.GetStudentInfo(studentModel.Id);
if (existingStudent.StudentType == "Day Scholar")
{
returnVal = true;
}
else
{
returnVal = false;
}
return returnVal;
}
The Test method:
public void AllowStudentUpdates_Success()
{
var studentModel = new StudentModel()
{
StudentName = "Joe",
Id = "123",
StudentType = "Day Scholar"
};
var studentToAdd = new Student()
{
Id = "123",
Name = "Joe",
StartDate = DateTime.UtcNow.ToShortDateString(),
StudentType = "Day Scholar",
EndDate = "08/10/2016"
};
_studentRulesHelper.Setup(x => x.GetStudentRule(studentModel, true)).Returns(studentToAdd);
_productRulesHelper.Setup(x => x.ReturnStudentRule(studentModel, true)).Returns(studentToAdd);
var res = _controller.UpsertStudent(studentModel) as JsonResult;
if (res != null) Assert.AreEqual("{ result = True }", res.Data.ToString());
}
When it hits the UpsertDoc call, it goes to the actual call in the controller and tries to execute CheckStudentUpdateForEdit() the GetStudentInfo() tries to get an object from the db and returns a null object as there is no student with the id that's passed from the test method.
The test then fails with Null Reference exception.
Now the system under test is not supposed to hit the db. I don't know why this is doing the other way!
Anyone else writing this test will also try to pass a dummy object which is bound to fail at GetStudentInfo() the way the test is setup now.
What do I do to make this work?
I am not sure if I have understood you problem correctly, but looking at the code snippets provided, the test will go and hit the database, because the mock object and its expectation is not defined.
I would have implemented the solution like this -
I am making some assumptions that your _updateStudentManager object is for the class that is doing the DB interaction for Student. I'll call it say StudentRepository. And to allow you to mock the behavior I would make it Interface driven.
So typically my setup would look like this -
//Interface
public interface IStudentrepository
{
StudentModel GetStudentInfo(int studentId);
}
//Class implementing IStudentrepository
public class StudentRepository : IStudentrepository
{
public StudentModel GetStudentInfo(int studentId)
{
//Implementation goes here
}
}
Now in my controller, I would have an instance of IStudentrepository, which can be injected via constructor.
public class StudentController
{
private readonly IStudentrepository updateStudentManager;
public StudentController(IStudentrepository updateStudentManager)
{
this.updateStudentManager = updateStudentManager;
}
}
//Rest of the code for controller....
Now while writing my Test, I will create a mock object of IStudentrepository, define the expectation for the mock object, and inject it when creating the controller object. Something like this.
[TestMethod]
public void TestMethod1()
{
//--Arrange--
//Define a mock object for student repository
var mock = new Mock<IStudentrepository>();
//Define the expectations of the mock object
mock.Setup(s => s.GetStudentInfo(It.IsAny<int>()))
.Returns(new StudentModel {/*return the required object */ });
//Instantiate controller and inject the mock object
StudentController _controller = new StudentController(mock.Object);
//--Act--
var res = _controller.UpsertStudent(studentModel) as JsonResult;
//--Assert--
if (res != null) Assert.AreEqual("{ result = True }", res.Data.ToString());
}
Now when your test method calls the GetStudentInfo method, instead of hitting the db, it will return the value as set in mock object.
This is just a high level implementation, and of course you can modify it as per your design. Hope it helps
The is driving me nuts. Im trying to do a "simple" record insert and I can only get it to work if I store the context in a variable or create a local context. I tried to keep the context and model object tied together but no luck so far.
public class TransactionDataAccessLayer
{
public cartableContext transactionContext
{
get
{
return new cartableContext();
}
}
}
class TransactionBusinessLayer
{
Cardata newCar = new Cardata();
public void addCar(Cardata cd)
{
try
{
//this works. Storing the context in ctc2 seems to make it work???
TransactionDataAccessLayer tdal = new TransactionDataAccessLayer();
cartableContext ctc2 = tdal.transactionContext;
ctc2.cardata.Add(cd);
ctc2.SaveChanges();
//this does not work
tdal.transactionContext.cardata.Add(cd);
tdal.transactionContext.Entry(cd).State = EntityState.Modified;
tdal.transactionContext.SaveChanges();
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
}
}
}
In C#, properties are basically just fancy methods, designed to make it easier to access private fields. Therefore, returning a new Context in your getter will do just that; return a new one each time it is accessed. To preserve state, you need to contain your context in a private field, like so:
public class TransactionDataAccessLayer
{
private cartableContext _transactionContext;
public cartableContext transactionContext
{
get
{
if (_transactionContext == null)
_transactionContext = new cartableContext();
return _transactionContext;
}
}
}
I have the following repository method:-
public RackJoin AllFindRackDetails_J(int id)
{
var tmsRack = tms.TMSRacks
.Include(a=>a.Zone)
.Include(a2=>a2.DataCenter)
.Include(a3=>a3.Technology)
.SingleOrDefault(a3=>a3.TMSRackID == id);
var IT360Rack = entities.Resources
.Include(a => a.ComponentDefinition)
.Include(a=>a.ResourceLocation.SiteDefinition.SDOrganization)
.Include(a=>a.ResourceLocation.SiteDefinition.AccountDefinition.SDOrganization)
// .Include(a=>a.CI)
.SingleOrDefault(a2=>a2.RESOURCEID == tmsRack.Technology.IT360ID);
RackJoin rj = new RackJoin {
Rack = tmsRack,
Resource = IT360Rack,
Technology = tmsRack.Technology,
ComponentDefinition = IT360Rack.ComponentDefinition,
Site = IT360Rack.ResourceLocation.SiteDefinition.SDOrganization,
Customer = IT360Rack.ResourceLocation.SiteDefinition.AccountDefinition.SDOrganization
};
return rj;
}
which is called from the following action method:-
public ActionResult Details(int id,string detailName=null)
{
var racks = repository.AllFindRackDetails_J(id);
return View(racks);
}
I know that in case the repository method returns IQurable<> then the database will be hit once I iterate over the Iqurable or call .list(). But what will happen in case the repository method can only return single object, when the actual data base interaction will happen?
SingleOrDefault causes the query to be executed immediately. This is true for all LINQ-to-X extension methods on IQueryable<T> which return something other than IQueryable<T>. For example First, Count, or Max all execute immediately.
This ought to be simple enough, although I find I can only set cookies but not read them back, despite my browser showing me the cookie.
In my HomeController I set the cookie once a user enters a valid string:
[HttpPost]
public ActionResult Index(string fMemberCode)
{
try
{
// TODO: controller-->member table module-->member data gateway-->DB
// Check member num against member table
// Return cookie if exists
// Return error if not
MembersModule membersModule = new MembersModule();
int memberId = membersModule.AuthMember(fMemberCode);
if (memberId > 0)
{
HttpCookie mCookie = new HttpCookie("MMedia");
mCookie.Value = memberId.ToString();
Response.Cookies.Add(mCookie);
}
else { }
return RedirectToAction("Index");
}
catch
{
return View();
}
}
Then later on, in a different context, the LibraryController needs to check the cookie is present:
public LibraryController()
{
// TODO
// Check member cookie present
int id = int.Parse(Request.Cookies["Media"].Value);
if (id > 0)
this.module = new LibraryModule(id);
else throw new Exception("Invalid cookie");
}
However, when stepping through the code in VS2012 when the line of execution in LibraryController reaches:
int id = int.Parse(Request.Cookies["Media"].Value);
The exception is thrown: Object reference not set to an instance of an object
You can't access the Request property in the constructor of your controller. It doesn't exist at that point in the controller life cycle.
Perhaps an action or controller filter might help you.
I'm working with ASP.Net MVC4, I customize my login, this is ok, I would like save this object USER and I can access from differents controllers and differents Areas. I was trying to defined this object as "static" but I can't acces to values of object:
if (Servicio.ValidarUsuario())
{
string Mensaje = "";
Models.AdmUsuario oAdmUsuario = new Models.AdmUsuario();
oAdmUsuario.Au_codusuario = login.UserName;
Servicio.RetornaEntidad<Models.AdmUsuario>(ref Mensaje, "admsis.adm_usuario", oAdmUsuario.getPk(), oAdmUsuario);
***Models.AdmUsuario.UserWeb = oAdmUsuario;***
FormsAuthentication.SetAuthCookie(login.UserName, false);
Session["Modulo"] = null;
Session["Menu"] = null;
return RedirectToAction("index", "raMainReclamo", new { area = "Reclamos" });
}
In the model I define:
public static AdmUsuario UserWeb;
But I can't access to value.
Do you have any idea, how I can to access the values of an object from different controllers in different areas?
You need a way to store the object between requests. You could put the object in Session Memory and pull it back out.
{
// Other Code
Session["AdmUsuario"] = oAdmUsuario;
return RedirectToAction("index", "raMainReclamo", new { area = "Reclamos" });
}
Controller in Reclamos Area
public class raMainReclamoController : Controller
{
public ActionResult Index() {
var oAdmUsuario = Session["AdmUsuario"] as Models.AdmUsuario;
// Other Code
}
}
However, the a more standard approach would be to persist the object to a database and then pull it back out. You could read up on using Entity Framework to access a sql database. I like to use RavenDB for storage as it makes saving objects really easy.
** UPDATE IN RESPONSE TO COMMENTS **
This is just psuedo code as I don't know what you are using to connect to postgres.
{
// Other Code
oAdmUsuario = postgresContext.Store(oAdmUsuario);
postgresContext.SaveChanges();
return RedirectToAction("index", "raMainReclamo", new { area = "Reclamos", id = oAdmnUsuario.Id });
}
Controller in Reclamos Area
public class raMainReclamoController : Controller
{
public ActionResult Index(int id) {
var oAdmUsuario = postgresContext.GetById<Models.AdmUsuario>(id);
// Other Code
}