Storing a value globally across all pages - asp.net

This is an ASP.NET Forms project. When user enters his/her user name and password (in the Login page) I want to save the user name such that it can be retrieved in the code of any page of the project. I know that I can do it via a session variable.
But is it possible to create a Static Public class with Get Set and store the value there and retrieve it using this class?

If you are using master page create a hidden field in that store that information in that hidden value so you can access in any page where you are using that master page.

Static classes are shared across instances/sessions in your app, which means you could end up with something akin to race conditions; for instance, a request from User_A could read values that were set in your static class by User_B. (see this SO answer)
Shooting from the hip, it might be easier to write a wrapper/abstraction class for your users' info that makes accessing their details easier. Something like:
public class UserDetails{
public string Name;
public string Age;
public string Gender;
public UserDetails(HttpContext context){
this.Name = context.User.Identity.Name;
this.Age = ...;
this.Gender = ...;
// Alternatively, you could perform your own data access to
// get/set these details. It depends on how you're storing your
// users' info.
}
}
Then in your code behind...
UserDetails userDetails = new UserDetails(context.Current);
Response.Write(userDetails.Name); // user's name
Response.Write(userDetails.Age); // user's age
...

Related

Store a variable in memory that can be get and modify for all users in web api netcore?

In my web api, I need to store a list in memory that can be accessed by all users and each time, each user request to api, an object will be add to that list. I had defined that list in a static class but when i debug, each time user request, the list still the same value when first time defined.
my static class:
public static class Images{
private static List<string> _imageStorage = new List<string>(){img1, img2, img3};
public static AddImageId(string id){
_imageStorage.Add(id); #It still 3 values when debug
}
}

ViewModel type architecture from Controller to View

I have a fairly complex class of Policies, of which I display a checkbox list of them, the user checks which one they want, and returns back to the server via ajax. The class is fairly complex:
public class Policy {
public int PolicyId { get; set; }
public string PolicyName { get; set; }
... another 15 properties ...
}
To display the list of checkboxes I really only need the Id and Name, so I've created a lightweight class PolicyViewModel that is simply:
public class PolicyViewModel {
public int PolicyId { get; set; }
public string PolicyName { get; set; }
}
So I then pass a List to the View and get a List back containing the selected Policies.
Another developer on my team said that he doesn't necessarily want to translate from the ViewModel to the Policy class on the Ajax call to save the selected policies, but I'm resistant to send a List of policies due to how heavy they are to send to the view, retrieving all the properties, etc.
EDIT: For clarification, on the Ajax save method, to persist to the DB, the call needs a list of the full Policy class.
What is the best way to display this list and get back the values? Is there a better way than I am proposing?
Usually, you wouldn't need a separate model when serializing to json. Simply pluck out what you need from the domain object into an anonymous object.
return policies.Select(x => new { PolicyId = x.PolicyId, Name = x.PolicyName});
on the return trip, you shouldn't have to send anything more than the Ids of the policies that the user selected. Those can be easily mapped back to your policy objects.
public Whatever PostPolicyChoices(IEnumerable<int> ids)
{
var checked = _context.Policies.Where(x => returnIds.Contains(x.PolicyId));
// snip
boom. done.
I will recommend you not to work with Domain objects in your mvc application . You must work just with ViewModels, I think this is best practice for mvc projects. Take a look at Automapper and use it in your project, this will simplify your work, so this should look something like this :
in your [HttpGet] method you will have :
var model =Mapper.Map<IList<Policy>,IList<VmSysPolicy>>(yourlist)
And in your [HttpPost] method you will have :
var domainList=Mapper.Map<IList<VmSysPolicy>,IList<Policy>>(modelList);
And in your mapping configuration you will do :
Mapper.CreateMap<Policy,PolicyVmSysPolicy,>()
.ForMemeber()//Your mapping here
and
Mapper.CreateMap<VmSysPolicy,Policy>()
.ForMemeber//mapping here

ASP.NET MVC - Posting a form with custom fields of different data types

In my ASP.NET MVC 2 web application, I allow users to create custom input fields of different data types to extend our basic input form. While tricky, building the input form from a collection of custom fields is straight-forward enough.
However, I'm now to the point where I want to handle the posting of this form and I'm not certain what the best way to handle this would be. Normally, we'd use strongly-typed input models that get bound from the various statically-typed inputs available on the form. However, I'm at a loss for how to do this with a variable number of input fields that represent different data types.
A representative input form might look something like:
My date field: [ date time input
control ]
My text field: [ text input
field ]
My file field: [ file upload
control ]
My number field: [ numerical input control ]
My text field 2: [text input field ]
etc...
Ideas I've thought about are:
Sending everything as strings (except for the file inputs, which would need to be handled specially).
Using a model with an "object" property and attempting to bind to that (if this is even possible).
Sending a json request to my controller with the data encoded properly and attempting to parse that.
Manually processing the form collection in my controller post action - certainly an option, but I'd love to avoid this.
Has anyone tackled an issue like this before? If so, how did you solve it?
Update:
My "base" form is handled on another input area all together, so a solution doesn't need to account for any sort of inheritence magic for this. I'm just interested in handling the custom fields on this interface, not my "base" ones.
Update 2:
Thank you to ARM and smartcaveman; both of you provided good guidance for how this could be done. I will update this question with my final solution once its been implemented.
This is how I would begin to approach the issue. A custom model binder would be pretty easy to build based on the FormKey property (which could be determined by the index and/or label, depending).
public class CustomFormModel
{
public string FormId { get; set; }
public string Label { get; set; }
public CustomFieldModel[] Fields { get; set; }
}
public class CustomFieldModel
{
public DataType DateType { get; set; } // System.ComponentModel.DataAnnotations
public string FormKey { get; set; }
public string Label { get; set; }
public object Value { get; set; }
}
public class CustomFieldModel<T> : CustomFieldModel
{
public new T Value { get; set; }
}
Also, I noticed one of the comments below had a filtered model binder system. Jimmy Bogard from Automapper made a really helpful post about this method at http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/03/17/a-better-model-binder.aspx , and later revised in, http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/11/19/a-better-model-binder-addendum.aspx . It has been very helpful for me in building custom model binders.
Update
I realized that I misinterpreted the question, and that he was specifically asking how to handle posting of the form "with a variable number of input fields that represent different data types". I think the best way to do this is to use a structure similar to above but leverage the Composite Pattern. Basically, you will need to create an interface like IFormComponent and implement it for each datatype that would be represented. I wrote and commented an example interface to help explain how this would be accomplished:
public interface IFormComponent
{
// the id on the html form field. In the case of a composite Id, that doesn't have a corresponding
// field you should still use something consistent, since it will be helpful for model binding
// (For example, a CompositeDateField appearing as the third field in the form should have an id
// something like "frmId_3_date" and its child fields would be "frmId_3_date_day", "frmId_3_date_month",
// and "frmId_3_date_year".
string FieldId { get; }
// the human readable field label
string Label { get; }
// some functionality may require knowledge of the
// Parent component. For example, a DayField with a value of "30"
// would need to ask its Parent, a CompositeDateField
// for its MonthField's value in order to validate
// that the month is not "February"
IFormComponent Parent { get; }
// Gets any child components or null if the
// component is a leaf component (has no children).
IList<IFormComponent> GetChildren();
// For leaf components, this method should accept the AttemptedValue from the value provider
// during Model Binding, and create the appropriate value.
// For composites, the input should be delimited in someway, and this method should parse the
// string to create the child components.
void BindTo(string value);
// This method should parse the Children or Underlying value to the
// default used by your business models. (e.g. a CompositeDateField would
// return a DateTime. You can get type safety by creating a FormComponent<TValue>
// which would help to avoid issues in binding.
object GetValue();
// This method would render the field to the http response stream.
// This makes it easy to render the forms simply by looping through
// the array. Implementations could extend this for using an injected
// formatting
void Render(TextWriter writer);
}
I am assuming that the custom forms can be accessed via some sort of id which can be contained as a form parameter. With that assumption, the model binder and provider could look something like this.
public interface IForm : IFormComponent
{
Guid FormId { get; }
void Add(IFormComponent component);
}
public interface IFormRepository
{
IForm GetForm(Guid id);
}
public class CustomFormModelBinder : IModelBinder
{
private readonly IFormRepository _repository;
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
ValueProviderResult result;
if(bindingContext.ValueProvider.TryGetValue("_customFormId", out result))
{
var form = _repository.GetForm(new Guid(result.AttemptedValue));
var fields = form.GetChildren();
// loop through the fields and bind their values
return form;
}
throw new Exception("Form ID not found.");
}
}
Obviously, all the code here is just to get the point across, and would need to be completed and cleaned up for actual use. Also, even if completed this would only bind to an implementation of the IForm interface, not a strongly typed business object. (It wouldn't be a huge step to convert it to a dictionary and build a strongly typed proxy using the Castle DictionaryAdapter, but since your users are dynamically creating the forms on the site, there is probably no strongly typed model in your solution and this is irrelevant). Hope this helps more.
Take a peek at what I did here: MVC2 Action to handle multiple models and see if can get you on the right track.
If you use a FormCollection as one of your parameters to your action, you can then go thru that form collection looking for bits of data here or there in order to bind those values to whatever an then save the data. You are most likely going to need to take advantage of both strategy and command patterns to get this to work.
Best of luck, feel free to ask follow-up questions.
Edit:
Your method which does the work should look something like this:
private/public void SaveCustomFields(var formId, FormCollection collection) //var as I don't know what type you are using to Id the form.
{
var binders = this.binders.select(b => b.CanHandle(collection)); //I used IOC to get my list of IBinder objects
// Method 1:
binders.ForEach(b => b.Save(formId, collection)); //This is the execution implementation.
// Method 2:
var commands = binders.Select(b => b.Command(formId, collection));
commands.ForEach(c => c.Execute());
}
public DateBinder : IBinder //Example binder
{
public bool CanHandle(FormCollection collection)
{
return (null != collection["MyDateField"]); //Whatever the name of this field is.
}
//Method 1
public void Save(var formId, FormCollection collection)
{
var value = DateTime.Parse(collection["MyDateField"]);
this.someLogic.Save(formId, value); //Save the value with the formId, or however you wish to save it.
}
//Method 2
public Command Command(var formId, FormCollection collection)
{
//I haven't done command pattern before so I'm not sure exactly what to do here.
//Sorry that I can't help further than that.
}
}
I would think one of the best options is to create a custom model binder, which makes it possible to have custom logic behind the scenes and still very customizable code behind.
Maybe these articles can help you:
http://www.gregshackles.com/2010/03/templated-helpers-and-custom-model-binders-in-asp-net-mvc-2/
http://www.singingeels.com/Articles/Model_Binders_in_ASPNET_MVC.aspx
More specifically I would probably take as the controller argument a custom class with all "base" properties included. The class could then for example include a dictionary linking the name of each field to either just an object or an interface which you implement once for each data-type making it simple to process the data later.
/Victor

asp.net mvc custom model binding in an update entity scenario

Hi I have a question about model binding. Imagine you have an existing database entity displayed in a form and you'd like to edit some details, some properties eg createddate etc are not bound to the form, during model binding, these properties are not assigned to the model as they are not on the http post data or querystrong etc, hence their properties are null. In my controller method for update , Id just like to do
public ActionResult Update( Entity ent)
{
//Save changes to db
}
but as some properties are null in ent, they override the existing database fields which are not part of the form post data, What is the correct way to handle this? Ive tried hidden fields to hold the data, but model binding does not seem to assign hidden fields to the model. Any suggestions would be appreciated
You shouldn't be sending your entity to your view, you should send a slim version of it called a DTO (data transfer object) or ViewModel.
Only send the properties to the view (and hence the form that gets posted back) that you want the user to update with that action.
In your POST handler you can then validate and copy the properties across to your entity.
an AutoMapper can help if you have lots of properties
something like:
public class User
{
int id;
string name;
string email;
}
public class EditUserEmailDto
{
string email;
}
// get
public ActionResult EditEmail(int id,)
{
return View("EditEmail", new EditUserEmailDto());
}
// post
public ActionResult EditEmail(int id, EditUserEmailDto dto)
{
if(!ModelState.IsValid)
return View("EditEmail", dto);
var user = userRepo.Get(id);
user.email = dto.email;
userRepo.Save(user);
return;
}

How does versioning work with Flex remote objects and AMF?

Suppose I use the [RemoteClass] tag to endow a custom Flex class with serialization intelligence.
What happens when I need to change my object (add a new field, remove a field, rename a field, etc)?
Is there a design pattern for handling this in an elegant way?
Your best bet is to do code generation against your backend classes to generation ActionScript counterparts for them. If you generate a base class with all of your object properties and then create a subclass for it which is never modified, you can still add custom code while regenerating only the parts of your class that change. Example:
java:
public class User {
public Long id;
public String firstName;
public String lastName;
}
as3:
public class UserBase {
public var id : Number;
public var firstName : String;
public var lastName : String;
}
[Bindable] [RemoteClass(...)]
public class User extends UserBase {
public function getFullName() : String {
return firstName + " " + lastName;
}
}
Check out the Granite Data Services project for Java -> AS3 code generation.
http://www.graniteds.org
Adding or removing generally works.
You'll get runtime warnings in your trace about properties either being missing or not found, but any data that is transferred and has a place to go will still get there. You need to keep this in mind while developing as not all your fields might have valid data.
Changing types, doesn't work so well and will often result in run time exceptions.
I like to use explicit data transfer objects and not to persist my actual data model that's used throughout the app. Then your translation from DTO->Model can take version differences into account.

Resources