Removal of one value in an array in MVC - c#

I am using a few methods and interfaces in this one. What i need is for the method I'm making to just simply remove 1 value in an array of attributes. All of the stuff here was previously created by someone else, and I'm just creating the removal part for the attribute to be removed. At any rate, the method that does the profile attribute work and sets the value does some work on the back end. I have a method for a UserProfileAttributeSetRequest that looks like this:
public UserProfileAttributeSetRequest()
{
}
public UserProfileAttributeSetRequest(Guid userIdentifier, Dictionary<string, string> profileAttributes)
{
UserIdentifier = userIdentifier;
ProfileAttributes = profileAttributes;
}
This fires a method on the back end that will take in the information being passed to it and change whatever needs to be changed. The method I'm building in the controller probably needs some work, I'm still fairly new to MVC, but here's what I've got:
public ActionResult RemoveEmployeeID(UserInfo userInfo)
{
User usr = UserManager.GetUser(userInfo.UserGuid);
var empID = usr.ProfileAttributes.FirstOrDefault(e => e.ProfileAttributeID == 3);
usr.ProfileAttributes.Remove(empID);
UserProfileAttributeSetRequest upd = new UserProfileAttributeSetRequest();
}
I'm grabbing the complete user, and isolating the single attribute I want to be changed, but the Request complains when I put any parameters in it. What am I doing wrong?

try like this
var emp = usr.ProfileAttributes.Where(e => e.ProfileAttributeID == 3).FirstOrDefault();
usr.ProfileAttributes.Remove(emp);
you have to update the database after removing the item.

Related

Model Binding null versus User given null

I am fairly new to .net core c# and wanted to know the following.
Whenever we put thru a HTTPRequest with body, c# model binding binds the same to a complex object (in my case). But in cases, where the the body did not have certain attributes populated, the model binding marks those as null. But in some cases, the user might populate it as null. I want to differentiate this and depending upon the same, I want to know whether I can overwrite what is already present in DB. Or I can read from Db, merge with the new request and then write again. Please let me know if there is a way to approach this problem, thanks :)
Example
[HttpPut]
public HttpResponseMessage PutAlbum(Album album)
{
}
Album
{
public int songs;
public string name;
public string composer;
.
.
}
Request
Req 1
{
songs = 2,
name = "xyz"
}
Req 2
{
songs = 2,
name = "xyz"
composer = null
}
In Req1, model binding assigns to null. Whereas in Req2, the user assigns composer to null. Is there a easy and optimal way to differentiate the same ??

How to add example values for parameters in Swagger-UI built by Nancy.Swagger package?

I have used Nancy.Swagger package and MetadataModule to build a Swagger UI for my APIs (according to this link: https://github.com/yahehe/Nancy.Swagger/wiki/Nancy.Swagger-for-Nancy-v2).
I get the UI, but the problem is that I cannot add example values for the properties of the object, which is passed as a parameter in body.
I see, for example, this output:
Here, instead of the word "string", I would like to have a real example value. But I don't know how I can add example values in this approach, and I would appreciate any help.
Snippet from the API and the parameter (object of PRequest):
Post("/", async (x, ctx) =>
{
PRequest PostRequestModel;
try
{
postRequestModel = this.Bind<PRequest>();
}
Snippet from MetaDataModule:
Describe["Post"] = desc => desc.AsSwagger(
with => with.Operation(
op => op.OperationId("Post")
.Tag("User")
.Summary("Post a new User")
.Description("This creates a new user.")
.BodyParameter(bp => bp.Description("A PRequest object").Name("PRequest").Schema<PRequest>())
I know it has been absolutely ages since you opened this, but I figured I'd share anyways.
First you need a model, like so:
public class Model
{
public string ExampleString { get; set; }
}
You need to create an instance of this model filled with whatever examples you want.
var exampleModel = new Model() { ExampleString = "foobar" }
Then you can add it to the BodyParameter like so:
.BodyParameter(para => para.Name("Example").Schema(
new Schema() { Example = exampleModel }
).Build())
I just created a public static class to hold all my example objects, then I set them like Example = Examples.Example1. I think this is the most readable approach.
A couple problems exist with this approach that I haven't found a solution to (yet). One is that the Example object does not seem to respect whatever settings you're using for Json serialization. Also, I've been unable to get this working concurrently with the Model view, but the Model view was always mostly useless in my eyes anyway. I'll update this if I ever figure any of these issues out. :)

C# MemoryCache, Cannot find out what is happening

I created a service supporting my asp.net mvc controller. The service returns a List. It is a list of custom defined fields that I render in the the create and edit views. Since these fields are defined once I want to return a cache when available and when not, create the cache. Since I am testing I have not defined cache expiration.
When I execute the Edit action this service helps mapping the queried values to the cached list of customfields. What happens is that my object in cache is modified.
I am familiair that the MemoryCache contains a reference and that is does not contain a copy of the object. What I do not understand is why the MemoryCache is modified, when I am actually working with an object that - in my view - is not a reference to the cache and had been passed to the method and has no ref or out parameters defined. For me the reference is in a totally different scope?
I tried all sorts of things but I am missing the essential issue that is causing this behavior and I really want to figure out what is happening here. Is there a broader scope of the reference. Do local variables are still being shared among methods?
This is the method in the service that either returns the cached information, or queries the database and stores the result in the cache. It is used by the Create and Edit actions. Notice that the value property is defined as being null so that a Create actions starts with empty fields.
public IList<CustomField> GetCustomFields()
{
var result = MemoryCache.Default["cache_customfield"] as List<CustomField>;
if (result == null)
{
result = session.Query<CustomField>()
.AsEnumerable()
.Select(c => new CustomField
{
Id = c.Id,
Name = c.Name,
Value = null
})
.ToList();
MemoryCache.Default["cache_customfield"] = result;
}
return result;
}
public static IList<CustomField> MapValues(IList<CustomField> fields, IDictionary<string,string> values = null)
{
// the cached information still has value properties that are null
var a = MemoryCache.Default["cache_customfield"] as List<CustomField>;
foreach (var field in fields.OrderBy(x => x.Name))
{
var persistedValue = string.Empty;
values?.TryGetValue(field.Id, out persistedValue);
field.Value = persistedValue;
}
// the cached information suddenly has value properties that are defined, however the 'fields' parameter has no reference to the original information?!
var b = MemoryCache.Default["cache_customfield"] as List<CustomField>;
return fields;
}
I doubt these have much impact on the situation, but these are the actions on the controllers for Create and Edit.
public ActionResult Create()
{
var ticketService = BusinessServiceFacade.GetTicketService(RavenSession);
var vm = new TicketViewModel();
vm.Controls = ControlViewModel.CreateControls(ticketService.GetCustomFields());
return View(vm);
}
public ActionResult Edit(string id)
{
var ticketService = BusinessServiceFacade.GetTicketService(RavenSession);
var ticket = RavenSession.Load<Ticket>(id);
var customfieldValues = ticket.Attributes.ToDictionary(x => x.Name, x => x.Value);
var vm = new TicketViewModel(ticket);
var listOfCustomFields = TicketService.MapValues(ticketService.GetCustomFields(), customfieldValues);
vm.Controls = ControlViewModel.CreateControls(listOfCustomFields);
return View(vm);
}
So essentially, why is my cache modified in the MapValues method when the fields parameter has a scope on his own (not ref or out). Really want to understand what is going on here.
UPDATE:
After making the modification by supplying a new List reference I am not noticing any change.
It looks like the reference is still passed forward from the local variable to the newly created as parameter. One thing would be to entirely build up a new list with freshly created CustomField objects but when possible I would like to avoid that.
I am possibly making a simple mistake.
public ActionResult Create()
{
var ticketService = BusinessServiceFacade.GetTicketService(RavenSession);
var vm = new TicketViewModel();
var fields = ticketService.GetCustomFields();
vm.Controls = ControlViewModel.CreateControls(new List<CustomField>(fields));
return View(vm);
}
public ActionResult Edit(string id)
{
var ticketService = BusinessServiceFacade.GetTicketService(RavenSession);
var ticket = RavenSession.Load<Ticket>(id);
var customfieldValues = ticket.Attributes.ToDictionary(x => x.Name, x => x.Value);
var vm = new TicketViewModel(ticket);
var fields = ticketService.GetCustomFields();
var listOfCustomFields = TicketService.MapValues(new List<CustomField>(fields), customfieldValues);
vm.Controls = ControlViewModel.CreateControls(listOfCustomFields);
return View(vm);
}
Solution
Do a deep copy.
public static IList<CustomField> MapValues(IList<CustomField> fields, IDictionary<string,string> values = null)
{
// break reference, deep copy to new list
var oldList = (List<CustomField>) fields;
var newList = oldList.ConvertAll(c => new CustomField(c.Id, c.Name, c.Visible, c.Type, c.TypeFormat, c.Value));
foreach (var field in newList.OrderBy(x => x.Name))
{
var persistedValue = string.Empty;
values?.TryGetValue(field.Id, out persistedValue);
field.Value = persistedValue;
}
return newList;
}
TicketService.MapValues(ticketService.GetCustomFields()...
Within your Edit method, you call MapValues passing in the result of GetCustomFields, and that result is the cached list. So, within MapValues, all of a, b, and fields are references to the same list (the cached object). That's why you see the changes you make to fields also appear in b.
why is my cache modified in the MapValues method when the fields parameter has a scope on his own (not ref or out).
Yes, fields is scoped to the method. But I think you're confusing the difference between 1) changing the value of fields -- which is a reference to a list. And 2) changing the actual list that fields references. Yes, the changes you make to fields is scoped to this method (e.g. it won't affect the value that was passed in). However, as long as it points to a specific list, any changes you make to that list can be observed by other references to the same list. So, the scope of fields doesn't mean the changes you make to the list will be scoped to this method.
In response to the comment below, if you do something like this:
IList<CustomField> originalList = ticketService.GetCustomFields();
IList<CustomField> newList = new List<CustomField>(originalList);
and pass in the new list to MapValues (TicketService.MapValues(newList...) then the changes within MapValues won't affect the list referenced by the originalList. Because now you have two different lists.
Update: As commented below, I didn't notice you were modifying individual items within the list. So you need to deep-copy in that case. In this specific case, deep-copy isn't too bad since you only have a couple properties to copy:
IList<CustomField> originalList = ticketService.GetCustomFields();
IList<CustomField> newList = originalList
.Select(x => new CustomField
{
Id = x.Id,
Name = x.Name,
Value = x.Value
})
.ToList();
However, you can see how this could get problematic quickly as you have more properties or properties of complex types (need to copy properties of properties, etc.). There are solutions such as serializing/deserializing the object to copy but I'd consider a different design first. Like I said, in your case, I think manually copying a couple properties isn't too bad.

How to optimise ASP.NET MVC controller to minimise the number of database query

My controller has different methods that use the same result returned by a stored procedure called by a LINQ query,
Is there a way to create a global variable that contains the result after making only one call to the procedure ??
I tried creating a constructor but every time the variable (ListePays) is used a new query is executed
public class BUController : Controller {
private NAV_MAUIEntities db = new NAV_MAUIEntities();
public DbSet<liste_pays> ListePays;
public BUController() {
ListePays = db.liste_pays();
}
public JsonResult BillPh(string Pays) {
var x = from pays in ListePays
where pays.Pays.ToUpper() == Pays.ToUpper()
select pays.code_pays;
string CodePays = x.FirstOrDefault().ToString();
}
public JsonResult BillPh2(string Pays) {
var x = from pays in ListePays
where pays.Pays.ToUpper() == Pays.ToUpper()
select pays.code_pays;
string CodePays = x.FirstOrDefault().ToString();
}
}
If the methods are all called as part the processing of the same HTTP request, just make sure some central actor (say, the action method) calls the procedure and passes the result to each method.
public ActionResult MyAction()
{
var data = db.liste_pays();
Method1(data);
Method2(data);
return View();
}
On the other hand, if you want to share the result across HTTP requests, you can cache the result of the procedure call in a number of locations (this is not an exhaustive list):
In the ASP.NET session
In a static variable
In System.Web.Caching.Cache
Not knowing more about your specific scenario, I can't recommend one over the other. However, be aware that the two latter options will potentially share the data between users, which may or may not be what you want.
NOTE: As your code stands at the moment, the call to db.liste_pays() is inside the constructor of BUController, so it is called every time a controller is created, that is, every time a new incoming HTTP request arrives. In other words, your assumption that it is being called every time the variable is used is not entirely correct.
First of all, there is no need for a constructor into an ASP.NET MVC controller.
What you did, means that every time a user makes a call to this controller, a call will be made to the DB to retrieve all your "pays".
I assume you are using Entity Framework. And the way you use Linq is "LinqToEntities". Do not worry about your DB calls, those are managed by the entity framework.
So, now, you just have to use linq that way :
public JsonResult BillPh(string Pays)
{
string codePays = db.liste_pays.FirstOrDefault(f =>
f.Pays.ToUpper() == Pays.ToUpper())
.CodePays.ToString();
}
And the syntax for the query is called "Lambda expressions".
Good luck ;-)

Best way to populate a list (or something) and make several methods use it?

I have a console application with a few methods that:
insert data1 (customers) from db 1 to db 2
update data1 from db 1 to db 2
insert data2 (contacts) from db 1 to db 2
insert data2 from db 1 to db 2
and then some data from db 2 (accessed by web services) to db 1 (MySql), the methods are initialized on execution of the application.
With these inserts and updates I need to compare a field (country state) with a value in a list I get from a web service. To get the states I have to do:
GetAllRecord getAllStates = new GetAllRecord();
getAllStates.recordType = GetAllRecordType.state;
getAllStates.recordTypeSpecified = true;
GetAllResult stateResult = _service.getAll(getAllStates);
Record[] stateRecords = stateResult.recordList;
and I can then loop through the array and look for shortname/fullname with
if (stateResult.status.isSuccess)
{
foreach (State state in stateRecords)
{
if (addressState.ToUpper() == state.fullName.ToUpper())
{
addressState = state.shortname;
}
}
}
As it is now I have the code above in all my methods but it takes a lot of time to fetch the state data and I have to do it many times (about 40k records and the web service only let me get 1k at a time so I have to use a "searchNext" method 39 times meaning that I query the web service 40 times for the states in each method.
I guess I could try to come up with something but I'm just checking what best praxis would be? If I create a separate method or class how can I access this list with all its values many times without having to download them again?
Edit: should I do something like this:
GetAllRecord getAllStates = new GetAllRecord();
getAllStates.recordType = GetAllRecordType.state;
getAllStates.recordTypeSpecified = true;
GetAllResult stateResult = _service.getAll(getAllStates);
Record[] stateRecords = stateResult.recordList;
Dictionary<string, string> allStates = new Dictionary<string, string>();
foreach (State state in stateRecords)
{
allStates.Add(state.shortname, state.fullName);
}
I am not sure where to put it though and how to access it from my methods.
One thing first, you should add a break to your code when you get a match. No need to continue looping the foreach after you have a match.
addressState = state.shortname;
break;
40 thousand records isn´t necessarily that much in with todays computers, and I would definitely implement a cache of all the fullnames <-> shortname.
If the data don´t change very often this is a perfectly good approach.
Create a Dictionary with fullName as the key and shortName as the value. Then you can just do a lookup in the methods which needs to translate the full name to the short name. You could either store this list as a static variable accessible from other classes, or have it in an instance class which you pass to your other objects as a reference.
If the data changes, you could refresh your cache every so often.
This way you only call the web service 40 times to get all the data, and all other lookups are in memory.
Code sample (not tested):
class MyCache
{
public static Dictionary<string,string> Cache = new Dictionary<string,string>();
public static void FillCache()
{
GetAllRecord getAllStates = new GetAllRecord();
getAllStates.recordType = GetAllRecordType.state;
getAllStates.recordTypeSpecified = true;
GetAllResult stateResult = _service.getAll(getAllStates);
Record[] stateRecords = stateResult.recordList;
if (stateResult.status.isSuccess)
{
foreach (State state in stateRecords)
{
Cache[state.fullName.ToUpper()] = state.shortname;
}
}
// and some code to do the rest of the web service calls until you have all results.
}
}
void Main()
{
// initialize the cache
MyCache.FillCache();
}
and in some method using it
...
string stateName = "something";
string shortName = MyCache.Cache[stateName.ToUpper()];
An easy way would be (and you really should) to cache the data locally. If I understand you correctly you do the webservice check everytime something changes which is likely unneccessary.
An easy implementation (if you can't or don't want to change your original data structures) would be to use a Dictionary somewhat like:
Dictionary<String, String> cache;
cache[addressState] = state.shortname;
BTW: You REALLY should not be using ToUpper for case insensitive compares. Use String.Compare (a, b, StringComparison.OrdinalIgnoreCase) instead.
From what I gather all the first bit of code is in some form of loop, and because of which the following line (which internally does the call to the web service) is being called 40 times:
GetAllResult stateResult = _service.getAll(getAllStates);
Perhaps you should try moving the stateResult variable to a class level scope: make it a private variable or something. So at least it will be there for the life time of the object. In the constructor of the class or in some method, make a call to the method on the object which interfaces with the ws. If you've gone with writing a method, make sure you've called the method once before you execute your loop-logic.
Hence you wouldn't have to call the ws all the time, just once.

Categories

Resources