I put some properties in the App.xaml.cs file which I am using to store data and populate textboxes as I navigate through my application:
public String appRXName { set; get; }
public String appRXNumber { set; get; }
Originally I had a pivot control that called different pages to gather data, but then I moved that pivot control item off to its own page that still calls other pages to collect data. Now when I run the application I get an error.
Basically it was working when I had it inside the original Pivot control. Once I moved it to a separate page (pivot page calles it) then I started to get this error:
System.ArgumentNullException was unhandled Message=Value can not be null. Parameter name: Text
No matter what page I hit always the second item in the list displays the error.
txtRxNotes.Text = (Application.Current as App).appDosageNotes;
txtQuantity.Text = (Application.Current as App).appQuantity.ToString();
I found something online about a RootVisual but I'm not sure if that is what I looking at or not. Does anyone have any ideas?
The ArgumentNullException is being thrown because the value that you are trying to set for the Text property is null, which you cannot do; the Text property is not a nullable type.
Without knowing how and when these application-level properties are being set it's difficult to provide a good explanation of why the behavior is different since your refactor, but you could either:
Put a null check in the code that accesses these application-level properties.
Initialise the application-level properties to string.Empty in the application constructor.
Related
In an ASP .Net Core 2.1 Web API (with a MySQL database and using Pomelo), when I add a new entity to the database in one of my controller actions, if the entity that is received by the API from the consuming client has a value in the primary key, it appears as though EF Core is trying to add the primary key instead of allowing the database to give it a new value.
So... in the database, I have a table called person which has an integer field called id which is set to PRIMARY KEY and AUTO-INCREMENT.
Model:
public partial class Person
{
public int? Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
}
DbContext:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Person>(entity =>
{
entity.ToTable("person");
entity.HasKey(e => e.Id);
entity.Property(e => e.Id)
.HasColumnName("id")
.HasColumnType("int(11)");
entity.Property(e => e.Name)
.HasColumnName("name")
.HasColumnType("varchar(45)");
entity.Property(e => e.Surname)
.HasColumnName("surname")
.HasColumnType("varchar(45)");
}
}
Controller Action
// POST: api/Person
[HttpPost]
public async Task<IActionResult> AddPerson([FromBody]Person person)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
_context.Person.Add(person);
await _context.SaveChangesAsync();
return CreatedAtAction("GetPerson", new { id = person.Id }, person);
}
If I don't specifically clear the Id of the person before trying to insert it into the database (i.e. person.Id = null) then I get an exception complaining about duplicate primary key. Is this normal EF Core behavior? Or am I doing something wrong?
Frankly, yes, you are doing something wrong. For a whole host of reasons, you should never ever save an instance created from user input (i.e. the Person instance being passed into your action and created from the request body of the post) directly to your database. One such reason is that it causes havoc with ORMs like EF, which employ entity tracking to optimize queries.
Simply, this Person instance here is untracked - EF knows nothing about it. You then use Add to add it to your context, which signals EF to start tracking it as a new thing. When you later save, EF, then dutifully issues an insert statement, but since an id is included in that insert, you get a primary key conflict. What you wanted instead was for EF to do an update, but it doesn't know it should.
There's ways you can technically fix this. For example, you could use Attach rather than Add. That merely blindly tells EF that this is something it should track, without necessarily communicating that it should do anything with it. If you make any modifications to this instance after it is tracked, EF will change its change to "modified" and you'll end up with an update statement being issued when you save. However, if you're not making any changes, but just saving it directly, you'll also need to explicitly set it's state to "modified" or EF will essentially do nothing. The nice thing is that if you change the state on an untracked entity, then EF automatically attaches it to track said state, so you you don't need to do Attach manually. Long and short, you can clear the exception merely by replacing your Add line with:
_context.Entry(person).State = EntityState.Modified;
However, that then will cause a problem if you try to add a new person entirely. A bigger issue you have here is that you have one action doing double duty. According to REST, a POST is not replayable and should only be made to resources which or idempotent. Put more simply, you POST only to a resource like /api/person (rather than something like /api/person/1 and every time you do so a new person should be created. For an update, you should make a request to that actual resource, i.e /api/person/1 and the HTTP verb should be PUT, instead. The same PUT request to the same resource will always have the same result, which is the case for an update to a particular resource.
Theory aside, the simple point is that you should have two actions:
[HttpPost("")]
public async Task<IActionResult> AddPerson([FromBody]Person person)
[HttpPut("{id}")]
public async Task<IActionResult> UpdatePerson(int id, [FromBody]Person person)
Finally, even with all this, saving the person param directly puts too much trust in the user, when doing an update. There might be any number of properties an end-user should not be able to modify with an update (such as something like a "created" date, for example), but they can when you do this. In some ways worse, even if the user is not being malicious, you're still relying on them to post all the data for that entity. For example, if you did have a created date property, but the user doesn't post that with their update (honestly, why would you post a created date along with a request to update a resource), then it will have the effect of clearing that property out. If there's a default, it will be set back to that, and if not, you may actually get an exception on saving, if the column is NOT NULL.
Long and short, it's not a good idea. Instead, use a view model, DTO, or similar. That class should contain only properties you want to allow a user to modify or even to affect on create in the first place. Then, for the case of an update, you pull the resource fresh from the database, and map over the values from your param instance onto that. Finally, you save the version from the database back to the database. This ensures 1) the user cannot modify anything you do not explicitly allow, 2) the user only needs to post things they actually care about modifying, and 3) the entity will be properly tracked and EF will issue an update statement correctly on save.
I have tried to save login value as true if user has logged in once by using
Application.Current.Properties["isLoggedIn"] = "true";
but its not working. If i remove my app from background it again shows the login page but if user is logged in it should show the next page.
When using 'Application Properties Dictionary' you have to keep in mind few things:
According to the official documentation: 'The Properties dictionary is saved to the device automatically'. However, if you want to ensure persistence you have to explicitly call SavePropertiesAsync().
The Properties dictionary can only serialize primitive types for storage. Attempting to store other types such as List can fail silently.
Read the official documentation carefully and pay attention to details. Here is a code example:
private async Task SaveApplicationProperty<T>(string key, T value)
{
Xamarin.Forms.Application.Current.Properties[key] = value;
await Xamarin.Forms.Application.Current.SavePropertiesAsync();
}
private T LoadApplicationProperty<T>(string key)
{
return (T) Xamarin.Forms.Application.Current.Properties[key];
}
// To save your property
await SaveApplicationProperty("isLoggedIn", true);
// To load your property
bool isLoggedIn = LoadApplicationProperty<bool>("isLoggedIn");
Base on your needs you may consider Local Database or Settings Plugin instead. However for saving just a few primitive values Application Properties approach should be good enough.
Xamarin Forms now includes Xamarin Forms Essentials and contains the Preferences component that you need. Check out the official website and try it.
https://learn.microsoft.com/en-us/xamarin/essentials/preferences?tabs=ios
This is an example of how to manage preferences with Essentials.
To save a value for a given key in preferences:
Preferences.Set("my_key", "my_value");
To retrieve a value from preferences or a default if not set:
var myValue = Preferences.Get("my_key", "default_value");
To remove the key from preferences:
Preferences.Remove("my_key");
To remove all preferences:
Preferences.Clear();
Supported Data Types:
bool
double
int
float
long
string
DateTime
First we set the key and value using below code
Xamarin.Essentials.Preferences.Set("UserId", content.userId);
We can get the above value in any page of project using below code
Xamarin.Essentials.Preferences.Get("UserId", "");
Yo! As the topic says, I need to keep var's value through refresh. Thing is it's SessionKey. Other thing is it's generated automatically.
What I need to do is html <select> which won't lose data on refresh. Actually there're 2 <select>s which are filled programatically and you can pass data between them in real time. Then if I press save and page fails to validate these <select>s return to their original state. I already have it fixed, by keeping data in session and if it has certain key, <select>s are filled with correct data.
Why would I need automatically generated key? Well multi-tab working. If user would try to add 2+ new records to database at the same time (which is extreme, but possible), he needs to have that data kept under different keys so app can find desired stuff.
I could as well make client side validation, but... nope, just nope, too much work.
As for code, anything useful:
public ActionResult MethodUsedAfterPageLoad
{
...
Guid stronyGuid = Guid.NewGuid();
ViewData["strony"] = stronyGuid.ToString();
...
}
This way every refresh creates new Guid, but Guid is used as SessionKey!
If I do it following way:
public Class ControllerClass
{
private Guid stronyGuid;
...
}
This will reset variable, that's bad. Using static keyword is bad idea.
I have an application where each user can choose a custom layout. The layouts can be different and it's not just css styles but html as well.
I know that mvc would cache the layout, but having so many layouts I doubt it would fit in cache. So what would it be better to save templates in DB or on the disk?
FYI: DB that I'm using is MongoDB.
I would save the layouts on disk because at the moment I don't see any advantage in a database (unless you do). But one thing that is worth mentioning is that you can create a class derived from OutputCacheAttribute and have your saved result depend on the layout you're using.
Does the layout depend on user? You could use the VaryByCustom property to have it vary by user.
EDIT
Are your users allowed to change layouts dinamically? If yes, you should also have a guid associated to your users change it each time the layouts change so you return on your VaryByCustom method:
return string.Format("User-{0}-{1}", user.Id, user.LayoutUpdateGuid);
See the meaning of this? This way, when a user changes the layouts, they will see their pages updated immediately.
How to apply the VaryByCustom attribute in your situation
In your action method, you may use:
[OutputCache(Duration = 3600, VaryByCustom = "UserLayouts")]
public ActionResult Details(string param)
{
// Returning the view
}
Then, in your VaryByCustom method in your Global.asax.cs file:
protected override string VaryByCustom(string custom)
{
switch (custom)
{
case "UserLayouts":
//// Here you fetch your user details so you can return a unique
//// string for each user and "publishing cycle"
//// Also, I strongly suggest you cache this user object and expire it
//// whenever the user is changed (e.g. when the LayoutUpdateGuid is
//// changed) so you achieve maximum speed and not defeat the purpose
//// of using output cache.
return string.Format("User-{0}-{1}", user.Id, user.LayoutUpdateGuid);
break;
}
}
The missing piece
The missing piece here is that you need to store a value that I called LayoutUpdateGuid (I'm sure you'll find a better name) and change that value whenever a user changes his layouts => this will lead to a different string being returned by the VaryByCustom(string) method in the Global.asasx.cs which in turn will force your action method to run again and return the result with the updated layout.
Makes sense to you?
Note: I can't test the specific code I wrote here, but I am sure (apart from typos) it is correct.
I have a form that I have users fill out and then it gets e-mailed to me.
I am trying to get an example of how I would create an ID (based on my own conventions) that I can use to keep track of responses (and send back to the user so they can reference it later).
This is the convention I am striving for:
[YEAR]-[SERVICE CODE]-[DATE(MMDD)]-[TIME]
For example: "2012-ABC-0204-1344". I figured to add the TIME convention in the instance that two different users pick the same service on the same date rather than try to figure out how to only apply it IF two users picked the same service on the same date.
So, the scenario is that after the user goes through my wizards inputting their information and then click "Submit" that this unique ID would be created and attached to the model. Maybe something like #Model.UniqueID so that in an e-mail response I send to the user it shows up and says "Reference this ID for any future communication".
Thanks for any advice/help/examples.
In your post action
[HttpPost]
public ActionResult Create(YourModel model)
{
model.UniqueId = GenerateUniqueId(serviceCode);
}
public string GenerateUniqueId(string serviceCode)
{
return string.Format("{0}-{1}-{2}", DateTime.Now.Year, serviceCode, Guid.NewGuid().ToString().Replace("-",""); //remove dashes so its fits into your convention
}
but this seems as I'm missing part of your question. If you really want unique, use a Guid. This is what we've used in the past to give to customers - a guid or a portion of one. IF you use a portion of one ensure you have logic to handle a duplicate key. You don't need to worry about this though if using a full guid. If the idea is just to give to a customer then ignore the rest of the data and just use a guid, since it can easily be looked up in the database.