I want to make a simple message system.In messaged table there are three significant columns which are;
ID of the message
Sender's UserId
Receiver's UserName
I am getting the message's id from url and checking whether the logged in user is sender or receiver of that message. If not, i don't want them to see the message.
public ActionResult Details(int? id)
{
var result = db.Talep.Where(e => e.ID == id && (e.UserId ==
User.Identity.GetUserId().ToString() || e.Receiver == User.Identity.Name));
if (result == null)
{
return HttpNotFound();
}
Talep talep = db.Talep.Find(id);
return View(talep);
}
The fallowing code is not working, result never becomes null even though the statement is wrong. I tryed to use .Any extension but it didn't work. I hope someone can help.
.Where is going to always return and IEnumerable, which will never be null.
There are 2 ways to handle this:
change your if to this: if (!result.Any()) This will check if there are any items in the return list - if there are no items, you will return your error.
change your LINQ query to use FirstOrDefault() This will return the first item that matches your request, or null if no items match.
Also a side not... If you use FirstOrDefault(), after the if statement to check for null, you will know you have a Talep, so the last call to look up the talep by ID would be a waste. Just return View(result)
Related
I have researched various nullable reference handling posts, but not finding anything helpful. So what I am doing below to handle this null reference (it's a hack for now to stop the error page from displaying to users) is to essentially return the current id if a next record does not exist in my edit controller.
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var myInClause = new string[] { "a", "c", "k" };
var myQueryResults = await _context.MyClass.FindAsync(id);
int? NextIdObject = (from i in _context.MyClass
where myInClause.Contains(i.RowType) && (i.Id > myclass.Id)
select new { i.Id }).DefaultIfEmpty().First().Id;
if (!NextIdObject.Equals(0))
{
ViewBag.nextID = NextIdObject;
}
else
{
ViewBag.nextID = id;
}
if (myQueryResults == null)
{
return NotFound();
}
return View(myQueryResults);
}
I would prefer to just redirect to the index page (if they hit this error, it means they are done working through a queue anyway, no next record would ever exist here). Or maybe just keep the code as is and display a message on the button to indicate end of list. Any thoughts here. Note, using any +1 increment on the id does not work for me, as I don't need the user to see all id records, just the one's with a/c/k which is why I bring the myInclause variable in. If there is a better way to use the SQL sytanx of "IN" for Linq queries, I am all ears.
I would prefer to just redirect to the index page (if they hit this
error, it means they are done working through a queue anyway, no next
record would ever exist here)
You could use try...catch block simply like
try
{
var myInClause = new string[] { "a", "c", "k" };
var myQueryResults = await _context.MyClass.FindAsync(id);
int NextIdObject = (from i in _context.MyClass
where myInClause.Contains(i.RowType) && (i.Id > myclass.Id)
select new { i.Id }).DefaultIfEmpty().First().Id;
ViewBag.nextID = NextIdObject;
}
catch(Exception ex)
{
return RedirectToAction("Index");
//or return View("Index");
}
return View(myQueryResults);
I have a simple login form on my mvc application and it works correctly except for when you try to login with a user that isn't in the database.
It will throw an error Sequence contains no elements which makes sense since theres no matching users in the database although I try to handle it in the code it is not doing it.
// POST: Login User
[HttpPost]
public ActionResult Login(UserAccount user)
{
using (MyDbContext db = new MyDbContext())
{
var usr = db.Users.Single(u => u.UserName == user.UserName && u.UserPassword == UserPassword);
if (usr != null)
{
Session["UserID"] = usr.UserId.ToString();
Session["Username"] = usr.UserName.ToString();
return RedirectToAction("LoggedIn");
}
else
{
ModelState.AddModelError("", "Username or Password Incorrect");
}
}
return View();
}
Single will throw an exception if no match is found, or too many are found. Using SingleOrDefault like so returns null in the case where no match is found:
var usr = db.Users.SingleOrDefault(...)
This sets you up for the null check you're doing right afterwards.
So...As some people said in the comments above, you could just simply use the following query and then do your null check:
var usr = db.Users.SingleOrDefault(u => u.UserName == user.UserName && u.UserPassword == UserPassword);
That being said, I would recommend looking into using the built in ASP Identity framework for authentication and authorization - unless you need a custom implementation for your application, you can avoid a lot of testing (and potential bugs) as well as get a ton of cool out-of-the-box features. I would recommend checking out the resources here for more information.
I am having an issue in my project and wonder if some can pinpoint me to where i may have gone wrong. so basically in my project i have got an ActionResult method like so:
public ActionResult PartNumberManufacturer(string id)
{
var partNumber = _Context.PartNumberTable.FirstOrDefault(x => x.partNumberId == id);
return PartialView("PartNumberView", partNumber);
}
Then this is my view
#if (Model != null && !string.IsNullOrEmpty(Model.PartNumberManufacturer))
{
#if (Model.PartNumberManufacturer == "Fr")
{
<div>
<p> This product is developed in france </p>
#if (#Model.PartNumberManufacturer == "Ger")
{
<p> This Product is developed in Germany </p>
}
well the above code works fine. but the thing is that if you look back into my ActionResult controller method , i am using :
var partNumber = Context.PartNumberTable.FirstOrDefault(x => x.partNumberId == id);
FirstOrDefault of-course will only return the first found part number in the database.
This isnot what i am looking for i don't want it only to return the first found record , i want it to return all the records that match by the search query in the database. So in order to do and after a few research online i found that i had to return the results into a list and this made me amend my ActionResult method to like this:
public ActionResult PartNumberManufacturer(string id)
{
var _methodOfRepair = Context.PartNumberTable.Where(x => x.PartNumberId == id); // changed thisline
return PartialView("PartNumberView", partNumber);
}
so yeah i get the error message saying that:
{"'System.Data.Entity.Infrastructure.DbQuery' does not contain a
definition for 'PartNumberManufacturer'"}
i made those changes. what am i doing wrong here? or is there a different approach i can be recommended to in order to achieve this?
thank you for your time.
First recommendation, read about implementing the repository pattern.
Second, if you are sending a collection of objects to your View then your View need to be expecting that data type. Change the Model data type that your View is expecting.
Inside your View, you should iterate over every element and render it.
I am able to successfully call Backbone's HTTP POST and PUT methods and have them link up to my server using Asp.Net MVC.
The problem is that when I call the HTTP DELETE using model.destroy() I get this error...
The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Delete(Int32)' in 'GSASF.Controllers.AdminController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters
Right before I call model.destroy() I logged the id to the console and it was correct. This is my code. *Note that my model doesn't have a field called id but instead a field called HoverId. The database table already existed so I have to make due.
Delete: function(id) {
if (id) {
for (var i = this.collection.length - 1; i >= 0; i--) {
var item = this.collection.at(i);
if (item.get("HoverId") == id)
alert("Item to be destroyed ID: " + item.get("id"));
item.destroy();
};
}
[ActionName("SpaceToolTipEdit")]
[HttpDelete]
public ActionResult Delete(int id)
{
var imageHover = sr.GetImageHoverById(id);
if (imageHover != null)
{
sr.DeleteImageHover(imageHover);
return new HttpStatusCodeResult(200);
}
return new EmptyResult();
}
Ok, I feel dumb now.
The solution was all to simple. I had originally set the url attribute to my /{Controller}/{SpaceToolTipEdit} url. I was supposed to set this to the urlRoot attribute instead.
I am new to ASP.NET MVC and I wonder if the way I handled these cases is the most appropriate.
I have an "ArticleController", which has an action called "Details" (Used the auto-generate edit template).
By default, there is an optional id at the routing table,
and I want to know how to handle the cases when I don't receive any Id or when I receive a wrong id parameter.
In order to fix it I've wrote this (Note the DefaultValue attribute):
public ViewResult Details([DefaultValue(0)]int id)
{
Article article = db.Articles.Find(id);
if (article == null)
{
return View();
}
return View(article);
}
And at the view I've wrote this:
#if (Model == null)
{
<div>Wrong article id was given.</div>
}
else
{
// Handle as a normal case
}
You would have handled these cases differently? If yes, how?
I think the cleanest approach is to set up your routes so that when no ID is present, a user is routed to a different action. That's what the default route does. For example: /Articles/ will invoke ArticleController::Index(), and /Articles/4 will invoke ArticleController::Details(4).
As far as the case goes where an ID is not found, personally, I prefer to return a 404 error:
return new HttpNotFoundResult("This doesn't exist");
You can make your Id nullable like this:
public ViewResult Details(int? id)
If the user provides no id or an incorrect one, the id won't have a value which you can check with id.HasValue. If the id has a value, you can obtain it with id.Value.