Return dynamic object - c#

I have a simple data layer routine that performs a password update, the user passes in the following:
Current Password, New Password, Confirm New Password.
In my data layer (proc) checks a couple things such as:
Is the current password correct?
Is the new password and confirm password correct?
Has the new password been assigned in the past?
And so on...
Now I know I can simply create a class and returned a couple booleans:
public class UpdatePasswordResponse{
public bool CurrentPasswordCorrect {get;set;}
....(and so on)
}
But is there a way I can dynamically return that information to the biz layer in properties instead of creating a new class everytime (for every data layer routine)? I seem to remember thinking this was possible. I am pretty sure I read it somewhere but don't remember the syntax, can someone help me?

You can do this in .NET 4 with the use of the dynamic keyword.
The class you will want to return would be an ExpandoObject.
Basically, follow this pattern:
public object GetDynamicObject()
{
dynamic obj = new ExpandoObject();
obj.DynamicProperty1 = "hello world";
obj.DynamicProperty2 = 123;
return obj;
}
// elsewhere in your code:
dynamic myObj = GetDynamicObject();
string hello = myObj.DynamicProperty1;

If you just want to dynamically create a class you write:
public object MyMethod()
{
var result = new { Username = "my name", Password = "the password" };
return result;
}

Related

Controller Method Get : Get specify attributes from a Class

my question is simple, I´m try to do a controller that pass some attributes of a Model
This is the method:
[HttpGet("getAllUserInfo")]
public async Task<ActionResult<object>> GetAll() {
var test = await _context.Users.ToListAsync(); //here I have the all Info of all users
//In the return I want pass some attributes of user, creating a new object (ex: The user have a password but I don´t want to show that)
return Ok(new { test.getType().Name, test.getType().Mail });
//this above is the part of the code I don´t understand
}
Is there any alternative to this scenario or what are the possible ideas to make this possible?
Sorry if there are any spelling mistakes in the title and document, but I think the idea where I have difficulty understanding is there
Are you just trying to project a list of objects into a new list of different objects? You can do that with .Select(). For example:
return Ok(test.Select(t => new { Name = t.Name, Mail = t.Mail }));

How to use variable static list when multi user access

this variable works fine if used by one user, but when used by two or more users then the "static" variable will be read by the next user, the first user instance when filling the gridview there are 5 rows of data and I try to access through other browser when entering the page, gridview on the second user already filled 5 rows of data in input by the first user. then how the solution to this problem? please see my code and give me an solutions. thanks.
static List<ServicesModels> _gridPackageDetail = new List<ServicesModels>();
private void AddListAction(string alfa, string beta)
{
ServicesModels data = new ServicesModels()
{
id_service_detail = Guid.NewGuid(),
scope_name = alfa,
detail_name= beta
};
_gridPackageDetail.Add(data);
}
public ActionResult GridPackageDetail()
{
ViewBag.DataListPackage = _gridPackageDetail.OrderBy(a => a.scope_name).ToList();
return PartialView();
}
my code in mvc3 controller.
The code is working fine, because this is what intended by "static", to have the same data for multi users. In your case you need to create a list or dictionary or multi-dimensional array (any data structure you are comfortABLE with) and save the data per use in it, and then retrieve the data when needed based on the user id.
static List<ServicesModels> _gridPackageDetail = new List<ServicesModels>();
private void AddListAction(string alfa, string beta)
{
ServicesModels data = new ServicesModels()
{
id_service_detail = Guid.NewGuid(),
scope_name = alfa,
detail_name= beta,
user_id = getTheID()// Get the id of the user
};
_gridPackageDetail.Add(data);
}
public ActionResult GridPackageDetail()
{
ViewBag.DataListPackage = _gridPackageDetail.OrderBy(a => a.scope_name && user_id ==getTheID()).ToList();
return PartialView();
}
replace getTheID() by your way of getting the id of the user.
This is used if you want to keep the data of all users. else you should remove the static keyword.

Dynamic return type for Form Flow

I'm currently looking for a way to dynamically create a FormDialog from values predefined in the database. In other words, my field types, prompts and settings are all stored in a database, and what I'm trying to achieve is reading those settings and building the appropriate form dynamically.
What I tried so far is something similar to the following. Suppose I have a form with a Name (string) and an Age (int) field (FieldDefinition is a class I created to store the parameters of a field, assuming they are fetched from the database) (The code is stripped just to illustrate the idea):
public static IForm<dynamic> BuildForm()
{
string FormMessage = "Welcome to demo contact form!";
string CompletionMessage = "Thank your for your info. Our team will contact you as soon as possible.";
var fields = new List<FieldDefinition>()
{
new FieldDefinition()
{
Name = "Name",
FieldType = typeof(string),
Prompts = new string[] { "What's your name?", "Please input your name" }
},
new FieldDefinition()
{
Name = "Age",
FieldType = typeof(int),
Prompts = new string[] { "What's your age?", "How old are you?" }
}
};
var builder = new FormBuilder<dynamic>();
builder.Message(FormMessage);
foreach (var f in fields)
{
builder.Field(
new FieldReflector<dynamic>(f.Name)
.SetType(f.FieldType)
);
}
builder.AddRemainingFields()
.OnCompletion(async (context, order) => {
var message = context.MakeMessage();
message.Text = CompletionMessage;
await context.PostAsync(message);
});
return builder.Build();
}
So here's the problems:
I thought I could use a dynamic type. But a method cannot return a dynamic object as it is determined at run-time. Therefore, I got an error when I tried building the form using the following:
dynamic values; var form = new FormDialog<dynamic>(values, ContactForm.BuildForm, FormOptions.PromptInStart, null);`
I need to create the properties of the object dynamically, therefore I looked for a way to create a Type on runtime. I ended up with something called TypeBuilder but I was a bit skeptical if it could solve my problem or not.
Therefore, I guess the ultimate start is by using the FieldReflector but I have no idea how to achieve this. I'm looking for something similar to the above but that does actually work.
Have you looked at FormBuilderJson? You could dynamically construct the .json string, and build the form at runtime:
public static IForm<JObject> BuildJsonForm()
{
string fromFlowJson = GetFormFlowJson();
return new FormBuilderJson(schema)
.AddRemainingFields()
.Build();
}
See here for more information: https://learn.microsoft.com/en-us/azure/bot-service/dotnet/bot-builder-dotnet-formflow-json-schema?view=azure-bot-service-3.0

How to MOQ Sitecore User object?

I need to do Moq test for the below original method
public virtual User GetBOUser(string domainName, string userName, string password, Login model)
{
try
{
if (Sitecore.Security.Accounts.User.Exists(domainName + #"\" + userName))
{
User user = Sitecore.Security.Accounts.User.FromName(domainName + #"\" + userName, true);
return user;
}
}
catch (Exception ex)
{
Log.Error("GetBOUser Error - " + ex.ToString(), this);
}
return null;
}
The sample unit test method I have created is below
[TestMethod]
public void LoginApiTest()
{
User use = null;
var mockapi = new Mock<ApiController>();
mockapi.Setup(x => x.GetBOUser("", "", "", new Login())).Returns(use);
var dataObject = mockapi.Object;
Assert.AreEqual<User>(use, dataObject.GetBOUser("", "", "", new Login()));
}
Here I am able to check only for null in the return type of test method, But how to return a actual user object ?
Before I address your question, I need to point out that your sample test is not actually testing anything. You are mocking your system under test, telling it to return null and then asserting that it returned null. This will not execute your production code.
You should be creating a normal instance of your ApiController. However, that highlights another issue in that your method has a dependency on Sitecore's static security API. If you want your code to be testable, you will need to create an interface and wrapper class for that API and make your controller accept an instance of your interface in its constructor so that you can provide a mock instance for your test but a real instance in production.
Your wrapper class should only call the static API and should contain no logic. That way you don't really need to test it. When you set up the mock instance of your interface you can create a mock IPrincipal and pass it to User.FromPrincipal to prevent it from actually trying to lookup the user in the database. If you were to name your interface IUserService, your test would end up looking something like this:
[TestMethod]
public void GetBOUser_WithExistingUser_ReturnsUser()
{
// Arrange
var name = "Joe";
var domain = "extranet";
var fullName = domain + #"\" + name;
var principal = new Mock<IPrincipal>();
principal.Setup(p => p.Identity.Name).Returns(fullName);
var joeUser = User.FromPrincipal(principal);
var userService = new Mock<IUserService>();
userService.Setup(u => u.Exists(fullName)).Returns(true);
userService.Setup(u => u.FromName(fullName)).Returns(joeUser.Object);
var controller = new ApiController(userService.Object);
// Act
var result = controller.GetBOUser("extranet", "Joe", "password", new Login());
// Assert
Assert.AreEqual(fullName, result.Name);
}
One other thing... Your GetBOUser method accepts a password, but does not validate it before returning a user. That is very misleading to consumers of your API. If you accept a password you should make sure it is correct before returning the requested user object.

c# class in a session state?

My senior project is building a reservation system in ASP.NET/C#. Part of my senior project is to have c# classes (and basically use everything ive learned in the past few years). One thing Im trying to do is after I instantiate a new "user" class I need it to travel between the pages. I know session states holds variables, so I figured a session state would work where I can simply type "Session["blah"]." and have access to its members. But I dont see that happening. I realize session states are HTTP context, so i doubted it would work anyway. But is there any other way in which I can accomplish what I need without instantiating a new user class every time? I know its a webpage...but im also trying to make it as much as a functional online program as I can.
Just for coder's sake, heres the code snippet im working with:
cDatabaseManager cDM = new cDatabaseManager();
string forDBPass = Encryptdata(pass_txt.Text.ToString());
string fullName = fname_txt.Text.ToString() + " " + lname_txt.Text.ToString();
cDM.regStudent(email_txt.Text.ToString(), forDBPass, fullName, num_txt.Text.ToString(), carrier_ddl.SelectedValue.ToString(), this);
//ADD - getting a cStudent
cUser studentUser = new cStudent(fullName, forDBPass, email_txt.Text.ToString());
//ADD - session states
Session["cStudent"] = studentUser;
//Session["cStudent"]. //session state will not work with what I am doing
//ADD - transfer to campus diagram
Thanks in advance!!
EDIT:
I want to thank all of you who posted and commented! Ive learned alot from this short discussion. All your answers helped me understand!
From your comment:
The issue is when I type "Session["cStudent"]." I don't have access to my functions. Example: Session["cStudent"].getName() does not give my functionality.
This is because the [] indexer for Session sets/returns objects. The compiler does not know that you stored a cUser object and so you can't access the properties directly without a cast:
string name = ((cUser)Session["cStudent"]).getName();
There are two things that could go wrong here:
If Session["cStudent"] is null you will get a NullReferenceException
If Session["cStudent"] is not really a cUser you will get an InvalidCastException
You should check these conditions and react appropriately if one of them is true.
Also, as others have pointed out, the cUser class needs to be marked as Serializable in order to be stored in Session state.
Session stores item as objects. As long as your class inherits from Object (which it does) you can store it there. Quick caveat, it stores that object using Serialization, so your class must be serializable.
Add a property to your class like so:
public cStudent CurrentStudent
{
get {
if(Session["CurrentUser"] == null)
return null;
return (cStudent)Session["CurrentUser"];
}
set {
Session["CurrentUser"] = value;
}
}
When retrieving an object value from session state cast it to appropriate type.
[Serializable]
public class student
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
In Page1:
student s1 = new student();
s1.FirstName ="James";
s1.LastName = "Bond";
Session["blah"] = s1;
And when you want to access Session["blah"] in page 2
student s2 = (Session["blah"] !=null ? (student)Session["blah"] : null);
Now you can access properties of s2 as s2.FirstName, s2.LastName

Categories

Resources