Trouble debugging asp.net mvc3 blog application : Sequence contains no elements - c#

i m currently working on a tutorial for a blog using ado.net and mvc3 (in c#). I m fairly new to developing so please cut me some slack! Anyways I m having trouble debugging one of the data controllers responsible for reading (validation is turned off) user posts and adding them to the blog. The code breaks down at the GetPost function (marked with a comment).
Any help would be greatly appreciated
` using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Blog.Models;
using System.Text;
namespace Blog.Controllers
{
public class PostsController : Controller
{
private BlogModel model = new BlogModel();
public ActionResult Index()
{
return View();
}
[ValidateInput(false)]
public ActionResult Update(int? id, string title, string body, DateTime dateTime, string tags)
{
if (!IsAdmin)
{
return RedirectToAction("Index");
}
Post post = GetPost(id);
post.Title = title;
post.DateTime = dateTime;
post.Body = body;
post.Tags.Clear();
tags = tags ?? string.Empty;
string[] tagNames = tags.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string tagName in tagNames)
{
post.Tags.Add(GetTag(tagName));
}
if (id.HasValue)
{
model.AddToPosts(post);
}
model.SaveChanges();
return RedirectToAction("Details", new { id = post.ID });
}
public ActionResult Edit(int? id)
{
Post post = GetPost(id);
StringBuilder tagList = new StringBuilder();
foreach (Tag tag in post.Tags)
{
tagList.AppendFormat("{0} ", tag.Name);
}
ViewBag.Tags = tagList.ToString();
return View(post);
}
private Tag GetTag(string tagName)
{
return model.Tags.Where(x => x.Name == tagName).FirstOrDefault() ?? new Tag() { Name = tagName };
}
/* Bellow is where I get the exception 'Sequence contains no elements' */
private Post GetPost(int? id)
{
return id.HasValue ? model.Posts.Where(x => x.ID == id).First() : new Post() { ID = -1 };
}
public bool IsAdmin { get { return true; } }
}
}
`
EDIT 16:29 GMT Yep you guys are right on the money! That went trough nicelly, thanks!
Whats weird is I m now getting Nullreference exception on this bit
post.Title = title;
post.DateTime = dateTime;
post.Body = body;
do I have to declare them somehow or am i missing something else?
Nevermind the edit above, that was just a typo. Thanks again

Try using FirstOrDefault(). If a LINQ expression yield no result, it is likely that with the methods First() or Single() you'll end up with the 'Sequence contains no elements' expection.
Edit: When using FirstOrDefault(), the Default means null. You need to check if GetPost returns null.

My guess is that model.Posts does not contain any elements and thus trying to perform a First() will cause the error you're getting.
Using FirstOrDefault() instead will return the default value of the type should no items be found in the collection.

Your problem is most likely that the results of the model.Posts.Where(x => x.ID == id) query are empty, which makes the First() method throw your error, which is the default behavior when querying the first element of an empty result set.
Try using FirstOrDefalut instead of First, which will returns null intead of throwing an exception. And of course, test if your result is null aftewards so you don't try using empty objects !

Related

JObject Parse Data with a variable as the value

I am trying to decipher the correct syntax for using JObject Parse when I need to have one of the values set by a variable. This is for using Algolia to push a new object to my search index.
songIndexHelper.PartialUpdateObject(JObject.Parse(#"{""ApprovalFL"":"true",
""objectID"":"'+Accepted.Value+'"}"));
I receive Accepted.Value from my function argument. For example, Accepted.Value could equal something like 98. Also, true should be formatted as boolean instead of a string. The above is my attempt. How should I fix my syntax?
I'm following this documentation from Algolia: https://www.algolia.com/doc/api-reference/api-methods/partial-update-objects/
For more context, here is the above line in the function:
public ActionResult Index(int? Accepted, int? Denied)
{
var accountInfo = EntityDataAccess.GetAccountInfoByUserID(User.Identity.GetUserId());
if(accountInfo == null || accountInfo.AdminFL == false || accountInfo.LabelFL == true)
{
return RedirectToAction("Index", "Home");
}
else
{
if(Accepted != null)
{
EntityDataAccess.AcceptSong(Accepted.Value);
var songIndexHelper = HttpContext.Application.Get("SongIndexHelper") as IndexHelper<SongAlgoliaModel>;
songIndexHelper.PartialUpdateObject(JObject.Parse(#"{""ApprovalFL"":""true"",
""objectID"":""Accepted.Value""}"));
}
This should produce what you are looking for:
String json = "{\"ApprovalFL\":true,\"objectID\":" + Accepted.Value.ToString() + "}";
which is:
{"ApprovalFL":true,"objectID":98}
songIndexHelper.PartialUpdateObject(JObject.Parse(#"{""ApprovalFL"":""true"",
""objectID"":""Accepted.Value""}"));
should be:
songIndexHelper.PartialUpdateObject(JObject.Parse(#"{""ApprovalFL"":true,
""objectID"":" +Accepted.Value+ "}"));
The key is to use + to concatenate in the value of Accepted, and not wrap true in quotes.
Another approach I would suggest is not using strings at all. Consider an approach like:
var bob = new { ApprovalFL = true, objectID = Accepted.Value};
var obj = JObject.FromObject(bob);
songIndexHelper.PartialUpdateObject(obj);

how to return IEnumerable<String> with linq. Getting Subquery returned more than 1 value

I want the query to give me back a NotificationConfiguration and also an IEnumerable<string> (which I will later transform to a single string using SB). Once the query gives me back those two items I will transform it using a constructor in my view model so I can properly display all the data using a DataTable. The answer I am looking for maybe very specific but I need to understand why I'm getting the subquery error when I want it to return an IEnumerable<string> and how to fix it. Also please note... according to the .net docs the code should be handing my back an IEnumerable<string> but for some reason its still crashing. Here is the relevant code samples again:
[HttpPost]
public ActionResult Index(DataTableRequest requestedData)
{
using (this.dataStore.Session.BeginTransaction())
{
return this.dataStore.Query<NotificationConfiguration>()
.TableRange(requestedData, p => new NotificationConfigurationViewModel(p, p.Events.Select(x => x.Code) ?? null));
}
}
.
public NotificationConfigurationViewModel(NotificationConfiguration notification , IEnumerable<string> events)
{
Contract.Requires(notification != null);
this.notification = notification;
this.events = events;
}
.
[Display(Name = "Events")]
public virtual string EventTypeCodes
{
get
{
var codes = new StringBuilder();
foreach (var item in this.events)
{
codes.Append(item + ",");
}
return codes.ToString().TrimEnd(',');
}
}

How does the asp.net mvc framework deals with Null values

I have some problem in understanding how does the asp.net mvc deal with Null values .
In the first scenario i have the following action method:-
[HttpPost]
public ActionResult Delete(int labtestid, int visitid)
{
try
{
var vlr = repository.GetVisitLabResult(labtestid,visitid);
string desc = vlr.LabTest.Description;
repository.DeleteVisitLabResult(vlr);
repository.Save();
return Json(new { IsSuccess = "True", id = labtestid, description = desc }, JsonRequestBehavior.AllowGet);
}
Incase the repository method var vlr = repository.GetVisitLabResult(labtestid,visitid); does not return any result (var vlr is null) then the following exception will be raised on the string desc = vlr.LabTest.Description; NullReferenceException was unhandled by user code. So why did the framework raise an exception instead of just assigning a null value to the string desc !!!
BR
It looks like the actual object itself is null. You have a null object and you're trying to access properties on it, hence the runtime will throw a NullReferenceException. You're best off checking if the object is null first before trying to access it's members :)

c# MVC XML Record Value

I have an xml file:
<profiles>
<profile username="user4" fullname="Full Name" />
</profiles>
I am trying to retrive the value of the fullname, here is what I tried:
public List<string> GetFullName(string username)
{
List<Profile> list = null;
try
{
list = (from t in ProfileList
where t.UserName == username
select t).FirstOrDefault();
}
catch { }
List<string> userFullName = new List<string>();
if (list != null)
{
foreach (Profile t in list)
{
userFullName.Find(t.FullName);
}
}
return userFullName;
}
FirstOrDefault gives an error!
Thanks in advance.
FirstOrDefault() is an extension method, which means that it's basically similar in concept to doing something like
var myList = new List<int>() { };
int myValue = StaticUtilsClass.FirstOrDefault(myList);
Now, if you look at FirstOrDefault documentation, notice that it throws a null argument exception when you pass in a null parameter.
What this means is that
List<int> myList = null;
myList.FirstOrDefault();
will throw an exception.
So, anytime you call x.FirstOrDefault(), and encounter a problem (i.e. an "error") the first thing to check is whether x, in this case, your query, is returning null.
From there, I would take a look at the fact that FirstOrDefault() is going to return a single entity, but you're setting it equal to a List<Profile>. Unless your ProfileList is an enumeration of List<Profile>, that's going to be a problem as well.
That should get you started anyway. Beyond that, it'd be helpful to know what ProfileList is and where it's declared.
I'd rather rewrite your code like this
public String GetFullName(string username)
{
var targetObject = (from t in ProfileList
where t.UserName == username
select t).FirstOrDefault();
if (targetObject != null) return targetObject.FullName;
throw new Exception("Target user is not found");
}

Get all values of a NameValueCollection to a string

I have the following code:
string Keys = string.Join(",",FormValues.AllKeys);
I was trying to play around with the get:
string Values = string.Join(",", FormValues.AllKeys.GetValue());
But of course that doesn't work.
I need something similar to get all the values, but I don't seem to find the appropriate code to do the same.
P.S: I do not want to use a foreach loop since that beats the purpose of the first line of code.
var col = new NameValueCollection() { { "a", "b" }, { "1", "2" } }; // collection initializer
var values = col.Cast<string>().Select(e => col[e]); // b, 2
var str = String.Join(",", values ); // "b,2"
Also you can create an extension method:
public static string Join(this NameValueCollection collection, Func<string,string> selector, string separator)
{
return String.Join(separator, collection.Cast<string>().Select(e => selector(e)));
}
Usage:
var s = c.Join(e => String.Format("\"{0}\"", c[e]), ",");
Also you can easily convert NameValueCollection to more handy Dictionary<string,string> so:
public static IDictionary<string,string> ToDictionary(this NameValueCollection col)
{
return col.AllKeys.ToDictionary(x => x, x => col[x]);
}
Gives:
var d = c.ToDictionary();
As I found using Reflector, NameValueCollection.AllKeys internally performs a loop to gather all te keys, so it seems that c.Cast<string>() is more preferable.
string values = string.Join(",", collection.AllKeys.Select(key => collection[key]));
Following creates a string from URL parameter list.
string.Join(", ",
Request.QueryString
.AllKeys
.Select(key => key + ": " + Request.QueryString[key])
.ToArray())
i.e
page.aspx?id=75&page=3&size=7&user=mamaci
would be
id: 75, page: 3, size: 7, user: mamaci
string values =
string.Join(",", FormValues.AllKeys.SelectMany(key => FormValues.GetValues(key)));
Edit: The other answers may or may not be what you want. They appear simpler, but the results might not be what you are looking for in all circumstances, but then again, they might be (your mileage may vary).
Note that a NameValueCollection is not a 1:1 mapping like a dictionary. You can add multiple values for the same key, which is why a function like .GetValues(key) returns an array, not a single string.
If you have a collection where you have added
collection.Add("Alpha", "1");
collection.Add("Alpha", "2");
collection.Add("Beta", "3");
Retrieving collection["Alpha"] yields "1,2". Retrieving collection.GetValues("Alpha") yields { "1", "2" }. Now, it just so happens that you are using a comma to join your values together into a single string, so this disparity is hidden. However, if you were joining on another value, such as an exclamation point, the results of the other answers would be
"1,2!3"
And the code here would be
"1!2!3"
Use the snippet that demonstrates the behavior you prefer.
In cases where you have parsed the query string with System.Web.HttpUtility.ParseQueryString(...) you can just use ToString() and you don't have to re-invent the wheel.
Even though result is NameValueCollection, the underlying type is HttpValueCollection which has the necessary ToString() override to build back a query string.
I'm using Azure DocumentDB as my logging mechanism, hence writing a dynamic object, but you get the gist...
public class LogErrorAttribute : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
int responseCode = new int();
// Has the exception been handled. Also, are custom errors enabled
if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
return;
// Check if custom exception, if so get response code
if (filterContext.Exception is CustomException)
responseCode = (int)((CustomException)filterContext.Exception).Code;
// Log exception
string id = Logging.Write(LogType.Error, new
{
ResponseCode = responseCode,
Exception = new
{
Message = filterContext.Exception.Message,
Data = filterContext.Exception.Data,
Source = filterContext.Exception.Source,
StackTrace = filterContext.Exception.StackTrace,
InnerException = filterContext.Exception.InnerException != null ? new
{
Message = filterContext.Exception.InnerException.Message,
Data = filterContext.Exception.InnerException.Data,
Source = filterContext.Exception.InnerException.Source,
StackTrace = filterContext.Exception.InnerException.StackTrace
} : null
},
Context = filterContext.Controller != null ? new
{
RouteData = filterContext.Controller.ControllerContext.RouteData,
QueryString = filterContext.Controller.ControllerContext.HttpContext.Request.Url.Query,
FormParams = filterContext.Controller.ControllerContext.HttpContext.Request.Form != null ? string.Join(";#", filterContext.Controller.ControllerContext.HttpContext.Request.Form.AllKeys.Select(key => key + ":" + filterContext.Controller.ControllerContext.HttpContext.Request.Form[key])) : string.Empty,
Model = (filterContext.Controller is Controller) ? ((Controller)filterContext.Controller).ModelState : null,
ViewBag = filterContext.Controller.ViewBag,
ViewData = filterContext.Controller.ViewData
} : null,
ActionResult = filterContext.Result != null ? filterContext.Result : null,
Referrer = filterContext.HttpContext.Request.UrlReferrer != null ? filterContext.HttpContext.Request.UrlReferrer : null
}).Result;
// Mark exception as handled and return
filterContext.ExceptionHandled = true;
// Test for Ajax call
if (IsAjax(filterContext))
{
// Construct appropriate Json response
filterContext.Result = new JsonResult()
{
Data = new
{
code = responseCode,
id = id,
message = filterContext.Exception.Message
},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
else
{
var result = new ViewResult();
result.ViewName = "_CustomError";
result.ViewBag.CorrelationId = id;
filterContext.Result = result;
}
}
/// <summary>
/// Determine if the request is from an Ajax call
/// </summary>
/// <param name="filterContext">The request context</param>
/// <returns>True or false for an Ajax call</returns>
private bool IsAjax(ExceptionContext filterContext)
{
return filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest";
}
}
I have a CustomException where I check for a application-set response code.
Additionally, I take the querystring, form data, and the model so that I can see the values passed before and after the model binder.
If its and Ajax call, I return a Json-formatted response. Otherwise, I return a custom error page.
List<string> values = new List<string>();
values.AddRange(all.AllKeys.SelectMany(all.GetValues).Where(getValues => getValues != null));
string Values = string.Join(",", values.ToArray());
You can try something like the above.

Categories