How to Assign value to List property - linq

I Have on object class which inherits from another object class, now every properties value is retrieving from DBs but only one property value is remaining and that i want to get from another method's variable
Code1:
var billDetails = await _billDetailsApiService.GetAllByBillId(userData.Id, singleBillDetails.Content.Id);
accountBillVM.BillDetails = billDetails.Content.ToList();
Here GetAllByBillId has List
Task<ApiResponse<List<BillHistoryDetails>>> GetAllByBillId(Guid id, long billId);
Object class
public class BillHistoryDetails : BillDetail
{
public string Name { get; set; }
public string BillName { get; set; }
}
ViewModel class
public List<BillHistoryDetails> BillDetails { get; set; }
How can I manualy store the value of BillName inside List
after getting value from
var getBillSessionType = await _billSessiontypeApiService.GetSingle(userData.Id, getBillSession.Content.BilllSessionTypeId, userData.AccountId);
so I could
BillName = getBillSessionType.Content.Name
but I am not getting value stored in BillName when I see the list content

Related

Bot User State property not able to read when specified in .lg file (Generated using Bot Framework Composer)

I have create a User State property in the code using the following code snippet:
userProfileProperty = UserState.CreateProperty<UserProfile>(nameof(UserProfile));
As can be seen above I am using a custom class object as the preoprty value i.e. UserProfile class, and this class holds various class properties as shown:
public class UserProfile
{
public string UserEmail { get; set; }
public string UserAlias { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
Now when I am trying to access the same property in a AdaptiveDialog flow by mentioning it in .lg file as shown below:
# bfdprompt-254582()
- what is your name
# bfdactivity-998627()
- Your name is #{user.name}
# bfdactivity-709726()
- Starting the First Dialog
# bfdactivity-496995()
- Test custom value is #{user.userprofile.useremail}
I am getting the following exception:
Please assist.
Try using the property name directly like below as long as you are sending the model UserProfile to the template engine
# bfdactivity-496995()
- Test custom value is #{useremail}
Take a look at this working example for more details:
private class UserLanguagePreference
{
public string OldLanguage { get; set; }
public string NewLanguage { get; set; }
}
We are fetching the response from the .lg file using the template engine like below:
UserLanguagePreference userLanguagePreference = new UserLanguagePreference
{
OldLanguage = _state.UserInfoState.LanguagePreference,
NewLanguage = PayloadsLanguageEnum.GetValueFromCode(payload).Name
};
await sc.Context.SendActivityAsync(_templateEngine.GenerateActivityForLocale("UpdateLanguagePreference", userLanguagePreference));
The .lg file has the following:
# UpdateLanguagePreference
- Language preference changed from : #{OldLanguage} to #{NewLanguage}

how to return multiple variable with jsonresult in mvc from controller to view?

in below code, i pass two parameters one is a list and second is viewbag message, but in view, side can't use viewbag.
So how to use it, please anyone help me
in view
where to i place viewbag message
create custom class
private class LineData
{
public string y { get; set; }
public string item1 { get; set; }
public string name { get; set; }
public string message { get; set; }
public List<LineData> list { get; set; }
}
In controller side
In view
As far as I understand to your question, you should create new class that holds both your list and message (instead of passing that to ViewBag).
public class YourResponse
{
public string Message { get; set; }
public List<SomeContent> Content { get; set; }
}
Then in your action in controller, create a new instance of this class and fill in the values and pass this instance back to the client.
public ActionResult YourActionName()
{
// do the stuff here to get message and list
var response = new YourResponse
{
Message = message, //insert your message here
Content = list //and list of data here
}
return Json(response);
}
And finally read and use the data from server within client code.
function OnSuccessed(data)
{
var message = data.Message;
var list = data.Content;
// you can work with message and list here
}
Just note that this is raw example, I have not run the code.

How do I make asp.net model collection properties null if not posted in json

I have this controller method:
public JsonNetResult Save(MyModel provider)
{
return GetJson(_serviceProviderService.Save(provider));
}
I post this json (captured via Fiddler):
{"Id":100,"Name":"Foo", "CreatedDate":"2013-02-20T15:32:07.85", "Models":null}
When reaching the Save method in the controller (breakpoint) the property Models has become an an empty collection.
I want to keep the null value on the Models property. How do I do that?
Reason: I want treat the null value as the Models collection was not "loaded" and will not be affected when saving the object graph; It should only be affected when it contains items.
Here is the ViewModel:
public class MyModel
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime CreatedDate { get; set; }
public List<EntityDisplayNameModel> Models { get; set; }
}

How do I maintain the type of items in a collection of a base type across postbacks?

I have a base class, a set of subclasses and a collection container that I am using to create and populate controls dynamically using partial views.
// base class
public class SQControl
{
[Key]
public int ID { get; set; }
public string Type { get; set; }
public string Question { get; set; }
public string Previous { get; set; }
public virtual string Current { get; set; }
}
// subclass
public class SQTextBox : SQControl
{
public SQTextBox()
{
this.Type = typeof(SQTextBox).Name;
}
}
//subclass
public class SQDropDown : SQControl
{
public SQDropDown()
{
this.Type = typeof(SQDropDown).Name;
}
[UIHint("DropDown")]
public override string Current { get; set; }
}
// collection container used as the Model for a view
public class SQControlsCollection
{
public List<SQControl> Collection { get; set; }
public SQControlsCollection()
{
Collection = new List<SQControl>();
}
}
I populate the Collection control with different subclasses of SQControl as required at runtime, and in EditorTemplates I have a separate view for each subclass. Using Html.EditorFor on the collection items I can dynamically generate the form with the appropriate controls.
This all works fine.
The problem I have is that when I save the form, MVC binding cannot tell what subclass each item in the Collection was created with and instead bind them to instances of the base class SQControl.
This confuses the View engine as it cannot determine the proper views to load anymore and simply loads the default.
The current workaround I have is to save the "Type" of the subclass as a field in the model, and on postback, I copy the collection into a new container, re-creating each object with the proper subclass based on the information in the Type field.
public static SQControlsCollection Copy(SQControlsCollection target)
{
SQControlsCollection newCol = new SQControlsCollection();
foreach (SQControl control in target.Collection)
{
if (control.Type == "SQTextBox")
{
newCol.Collection.Add(new SQTextBox { Current = control.Current, Previous = control.Previous, ID = control.ID, Question = control.Question });
}
else if (control.Type == "SQDropDown")
{
newCol.Collection.Add(new SQDropDown { Current = control.Current, Previous = control.Previous, ID = control.ID, Question = control.Question });
}
...
}
return newCol;
}
So my Question is, is there any better way to maintain the type of items in a base-typed-collection between postbacks? I understand it's practice in MVC to have a typed view for each model, but I want to be able to build a view on the fly based on an XML document using reusable partial views.

Get a model's property value from within a custom attribute

I have a custom attribute called FileLink that uses DisplayForModel() to generate an ActionLink to a controller with an ID value.
The attribute looks like this:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public sealed class FileLinkAttribute : Attribute
{
public string ActionName { get; set; }
public string ControllerName { get; set; }
public string IdPropertyName { get; set; }
public FileLinkAttribute(string actionName, string controllerName, string idPropertyName)
{
ActionName = actionName;
ControllerName = controllerName;
IdPropertyName = idName;
}
}
Is it used in a viewmodel, like so:
public class MyViewModel
{
[HiddenInput(DisplayValue = false)]
public int? Id { get; set; }
[HiddenInput(DisplayValue = false)]
public int? TargetId { get; set; }
[FileLink("SomeAction", "SomeController", "TargetId")]
public string Name { get; set; }
}
I have a custom MetadataProvider derived from DataAnnotationsModelMetadataProvider that puts the attribute values into the metadata AdditionalValues as so:
// retrieve the values to generate a file link
var fileLinkAttributes = attributes.OfType<FileLinkAttribute>();
if (fileLinkAttributes.Any())
{
var fileLinkAttribute = fileLinkAttributes.First();
metadata.AdditionalValues["FileLinkAttribute"] = fileLinkAttribute;
metadata.TemplateHint = "FileLink";
}
The goal is to have DisplayForModel call the DisplayTemplate below to generate a link with the value in TargetId from MyViewModel. So if TargetId is 5, the link will be "SomeController/SomeAction/5"
// This DisplayTemplate for use with the "FileLinkAttribute"
//
// Usage: [FileLinkAttribute("ActionName","ControllerName","IdPropertyName")]
var fileLinkAttribute = (FileLinkAttribute)ViewData.ModelMetadata.AdditionalValues["FileLinkAttribute"];
var targetId = *<GET VALUE OF CONTAINER MODEL IdPropertyName>*;
#Html.ActionLink((string)ViewData.Model, fileLinkAttribute.ActionName, fileLinkAttribute.ControllerName, new { Id = targetId}, null)
With all this in place, I am unable to access the containing object to pull the property value from TargetId. I have tried to do this within the Attribute, within the Provider, and within the DisplayTemplate, with no luck.
Is there a way or place I can access this value to accomplish my intent to read a property value from the viewmodel object containing the attribute?
After reading this post describing the purpose of modelAccessor in a custom DataAnnotationsModelMetadataProvider:
What is the "Func<object> modelAccessor" parameter for in MVC's DataAnnotationsModelMetadataProvider?
I was able to piece together this (very hackish) solution implemented in the custom provider:
// retrieve the values to generate a file link
var fileLinkAttributes = attributes.OfType<FileLinkAttribute>();
if (fileLinkAttributes.Any())
{
var fileLinkAttribute = fileLinkAttributes.First();
// modelAccessor contains a pointer the container, but the type is not correct but contains the name of the correct type
if (modelAccessor.Target.GetType().ToString().Contains("System.Web.Mvc.AssociatedMetadataProvider"))
{
// get the container model for this metadata
FieldInfo containerInfo = modelAccessor.Target.GetType().GetField("container");
var containerObject = containerInfo.GetValue(modelAccessor.Target);
// get the value of the requested property
PropertyInfo pi = containerObject.GetType().GetProperty(fileLinkAttribute.IdPropertyName);
string idPropertyValue = pi.GetValue(containerObject, null).ToString();
fileLinkAttribute.IdPropertyValue = idPropertyValue;
}
metadata.AdditionalValues["FileLinkAttribute"] = fileLinkAttribute;
metadata.TemplateHint = "FileLink";
}
I am not sure how to derefence a Func to get it's actual target, and the type name comes out all munged wierdly in this example, such as
"System.Web.Mvc.AssociatedMetadataProvider+<>c__DisplayClassb"
So I convert to a string to check if it contains "System.Web.Mvc.AssociatedMetadataProvider". Probably not the best thing but this is the only way I could get it to work.
Oh, I also added a 4th property to the attribute to contain the value:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public sealed class FileLinkAttribute : Attribute
{
public string ActionName { get; set; }
public string ControllerName { get; set; }
public string IdPropertyName { get; set; }
public string IdPropertyValue { get; set; }
public FileLinkAttribute(string actionName, string controllerName, string idPropertyName)
{
ActionName = actionName;
ControllerName = controllerName;
IdPropertyName = idPropertyName;
}
}
and in the DisplayTemplate I do:
var modelId = fileLinkAttribute.IdPropertyValue;
This should be an editor template for strsing or object as that'swhat you are applying the attribute on. So inside ~/Views/Shared/EditorTemplates/string.cshtml:
#model string
#{
var fileLinkAttribute = (FileLinkAttribute)ViewData.ModelMetadata.AdditionalValues["FileLinkAttribute"];
var targetId = fileLinkAttribute.IdPropertyName;
}
#Html.ActionLink(Model, fileLinkAttribute.ActionName, fileLinkAttribute.ControllerName, new { Id = targetId}, null)
and in your main view:
#Html.EditorFor(x => x.Name)

Resources