Parsing RSS 1.0 with C#/MVC 2 - asp.net-mvc-2

First, I cant believe that anyone in 2011 is still using RSS 1.0, guess you really learn something new. Well I'm trying to parse their feed and put the content on my clients site (I got permissions so no law breaking here). As you can imagine my first attempt failed miserably (was wrting code for 2.0) so I went back to the drawing board and here's what I've come up with.
RssController
public virtual ActionResult Index()
{
List<RssFeedItem> rssList = new List<RssFeedItem>();
XmlDocument doc = new XmlDocument();
XmlNamespaceManager manager = new XmlNamespaceManager(doc.NameTable);
manager.AddNamespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
manager.AddNamespace("rss", "http://purl.org/rss/1.0/");
XmlTextReader reader = new XmlTextReader("http://wdfw.wa.gov/news/newsrss.php");
doc.Load(reader);
XmlNodeList nodes = doc.SelectNodes("/rdf:RDF//rss:item",manager);
foreach(XmlNode node in nodes)
{
XmlNodeList aboutNode = node.SelectNodes("rss:about", manager);
XmlNodeList titleNode = node.SelectNodes("rss:title", manager);
XmlNodeList linkNode = node.SelectNodes("rss:link", manager);
var item = new RssFeedItem
{
Link = linkNode.Count == 0 ? "" : linkNode[0].InnerText,
Title = titleNode.Count == 0 ? "" : titleNode[0].InnerText,
About = aboutNode.Count == 0 ? "" : aboutNode[0].InnerText
};
rssList.Add(item);
}
return View(rssList);
}
I'm attempting to do this utilizing a partial view (ascs) and that looks like this
Index.aspx
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<GodsCreationTaxidermy.Models.RssFeedItem>" %>
<%
foreach (RssFeedItem item in (IEnumerable<RssFeedItem>)ViewData.Model)
{
Response.Write(string.Format("<div id={0}><a href={1} target=\"_blank\" /> <strong>{2}</strong></div>",
Model.About.Truncate(5), Model.Link, Model.Title.Truncate(25)));
} %>
Then I try RenderPartial in mySite.Master
<% Html.RenderPartial("Index");%>
The problem is that the site never even loads, or even gives some kind of error, it just sits tere with FF's litte loading icon spinning.
EDIT
Well I've made some major changes to my code from earlier, and same result, no error and it doesnt load the site even (just sits & spins). Here's the code from the Controller
[MoveFormsScript]
[CanonicalUrlAttribute("Rss")]
public virtual ActionResult Index()
{
return View(new RssList());
}
Now the code from RssList
[UIHint("Feeds")]
public SelectList Feeds { get; private set; }
[Required(ErrorMessage = "Rss Feeduired")]
public string Feed { get; set; }
public RssList()
{
this.Feeds = GetRssFeed(null);
}
public SelectList GetRssFeed(string selectedValue)
{
List<RssFeedItem> rssList = new List<RssFeedItem>();
XmlDocument doc = new XmlDocument();
XmlNamespaceManager manager = new XmlNamespaceManager(doc.NameTable);
manager.AddNamespace("rdf", "http://www.w3.org/1 999/02/22-rdf-syntax-ns#");
manager.AddNamespace("rss", "http://purl.org/rss/1.0/");
XmlTextReader reader = new XmlTextReader("http://wdfw.wa.gov/news/newsrss.php");
doc.Load(reader);
XmlNodeList nodes = doc.SelectNodes("/rdf:RDF//rss:item", manager);
foreach (XmlNode node in nodes)
{
XmlNodeList aboutNode = node.SelectNodes("rss:about", manager);
XmlNodeList titleNode = node.SelectNodes("rss:title", manager);
XmlNodeList linkNode = node.SelectNodes("rss:link", manager);
var item = new RssFeedItem
{
Link = linkNode.Count == 0 ? "" : linkNode[0].InnerText,
Title = titleNode.Count == 0 ? "" : titleNode[0].InnerText,
About = aboutNode.Count == 0 ? "" : aboutNode[0].InnerText
};
rssList.Add(item);
}
return new SelectList(rssList, "Link", "Title", selectedValue);
}
And finally my partial view
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<GodsCreationTaxidermy.Helpers.BusinessDTO.RssList>" %>
<%
foreach (var item in (IEnumerable<RssList>)ViewData.Model)
{
Response.Write(string.Format("<div id=\"{0}\"><a href=\"{1}\" target=\"_blank\" /> <strong>{2}</strong></div>",
item.Feed[0].ToString().Truncate(10), item.Feed[1], item.Feed[2].ToString().Truncate(100)));
} %>
Can anyone help me?

Change the instantiation of the XmlNodeList is the RssList class to:
XmlNodeList nodes = doc.SelectNodes("//rss:item[./rss:link]", manager);
Then change your ViewUserControl to this:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %><ul>
<%
RssList viewModel = ViewData.Model as RssList;
if (viewModel.Feeds.Count() > 0)
{
foreach (SelectListItem item in viewModel.Feeds)
{ %>
<li>
<%
Response.Write(String.Format("<a href='{0}' target='_blank'>{1}</a>", item.Value, item.Text));
}%>
</li>
<%
}
%></ul>
Seems to work for me.

There are a few problems I see here. Your control is expecting a single RssList, the Controller is returning a select list, and your foreach is enumerating over what it thinks is an IEnumerable<RssList>. Also, you're doing manual response.writes in the partial view. The markup would be cleaner if you didn't do that.
Let's start with the RssList class first. It looks like your first approach was actually what you wanted, the problem was just what you were doing in the partial view.
public class RssList
{
[UIHint("Feeds")]
public IEnumerable<RssFeedItem> Feeds { get; private set; }
[Required(ErrorMessage = "Rss Feed Required")]
public string Feed { get; set; }
public RssList()
{
this.Feeds = GetRssFeed(null);
}
public IEnumerable<RssFeedItem> GetRssFeed(string selectedValue)
{
List<RssFeedItem> rssList = new List<RssFeedItem>();
XmlDocument doc = new XmlDocument();
XmlNamespaceManager manager = new XmlNamespaceManager(doc.NameTable);
manager.AddNamespace("rdf", "http://www.w3.org/1 999/02/22-rdf-syntax-ns#");
manager.AddNamespace("rss", "http://purl.org/rss/1.0/");
XmlTextReader reader = new XmlTextReader("http://wdfw.wa.gov/news/newsrss.php");
doc.Load(reader);
XmlNodeList nodes = doc.SelectNodes(
"/rdf:RDF//rss:item[./rss:link./rss:title./rss:about]", manager);
foreach (XmlNode node in nodes)
{
XmlNodeList aboutNode = node.SelectNodes("rss:about", manager);
XmlNodeList titleNode = node.SelectNodes("rss:title", manager);
XmlNodeList linkNode = node.SelectNodes("rss:link", manager);
var rssItem = new RssFeedItem
{
Link = linkNode.Count == 0 ? "" : linkNode[0].InnerText,
Title = titleNode.Count == 0 ? "" : titleNode[0].InnerText,
About = aboutNode.Count == 0 ? "" : aboutNode[0].InnerText
};
rssList.Add(rssItem);
}
return rssList;
}
}
Now instead of a SelectList, we're returning an IEnumerable<RssFeedItem>. It's preferable not to manipulate the UI from the code if possible. So let's see if we need to work any magic on the controller. The only thing I see there is that you can exclude "Index" from the View function (it's implied because that is the name of the controller operation.
return PartialView(viewModel);
Now on to the view...let's see if we can make that look better
<%# Control Language="C#"
Inherits="System.Web.Mvc.ViewUserControl<GodsCreationTaxidermy.Helpers.BusinessDTO.RssList>" %>
<%
foreach (var rssItem in ViewData.Model.Feeds)
{
%>
<div id="<%=rssItem.Title%>">
<a href="<%=rssItem.Link%>" target="_blank">
<strong><%=rssItem.Title%></strong>
</a>
<%
}
%>
There I think that should do it for you...let me know if you run into any problems.

I'm not really familiar with the System.Web.Mvc.SelectList class much less the namespace, but I noticed your using a string for the selectedValue parameter. Should it be an RssFeedItem object instead?
[edit]
Ran your xml code section through some powershell hurdles and here's what I get.
$doc = New-Object Xml.XmlDocument;
$manager = New-Object Xml.XmlNamespaceManager $doc.NameTable;
$manager.AddNamespace("rdf", "http://www.w3.org/1 999/02/22-rdf-syntax-ns#");
$manager.AddNamespace("rss", "http://purl.org/rss/1.0/");
$reader = New-Object Xml.XmlTextReader("http://wdfw.wa.gov/news/newsrss.php");
$doc.Load($reader);
#doesn't work
"Doesn't work"
$doc.SelectNodes("//rss:item[./rss:link./rss:title./rss:about]", $manager) | measure | select count
#this is an invalid xpath query, there are no operators between the nodes specified in the [].
#Also, in the xml document we're looking at, there is no node named "about". "about" is an attibute to the "item" node.
#works
"Works"
$doc.SelectNodes("//rss:item[./rss:link and ./rss:title]", $manager) | measure | select count
#Even though we only have the "link" and "title" nodes in the [], everything is returned.
#That's because we're telling SelectNodes to return the "item" nodes themselves.

Can a mod merge this feed with this one MVC2 - Consume RSS feed with RDF and namespace http://www.w3.org/1999/02/22-rdf-syntax-ns#'. I forgot I had already asked

Made some more changes dor those who are trying to help me. Here's the controllers code
[MoveFormsScript]
[CanonicalUrlAttribute("Rss")]
public virtual ActionResult Index()
{
var viewModel = new RssList();
return PartialView("Index", viewModel);
}
Then I created a class (RssList), which is where the bulk of the work is done
RssList
[UIHint("Feeds")]
public SelectList Feeds { get; private set; }
[Required(ErrorMessage = "Rss Feed Required")]
public string Feed { get; set; }
public RssList()
{
this.Feeds = GetRssFeed(null);
}
public SelectList GetRssFeed(string selectedValue)
{
List<RssFeedItem> rssList = new List<RssFeedItem>();
XmlDocument doc = new XmlDocument();
XmlNamespaceManager manager = new XmlNamespaceManager(doc.NameTable);
manager.AddNamespace("rdf", "http://www.w3.org/1 999/02/22-rdf-syntax-ns#");
manager.AddNamespace("rss", "http://purl.org/rss/1.0/");
XmlTextReader reader = new XmlTextReader("http://wdfw.wa.gov/news/newsrss.php");
doc.Load(reader);
XmlNodeList nodes = doc.SelectNodes("/rdf:RDF//rss:item[./rss:link./rss:title./rss:about]", manager);
foreach (XmlNode node in nodes)
{
XmlNodeList aboutNode = node.SelectNodes("rss:about", manager);
XmlNodeList titleNode = node.SelectNodes("rss:title", manager);
XmlNodeList linkNode = node.SelectNodes("rss:link", manager);
var rssItem = new RssFeedItem
{
Link = linkNode.Count == 0 ? "" : linkNode[0].InnerText,
Title = titleNode.Count == 0 ? "" : titleNode[0].InnerText,
About = aboutNode.Count == 0 ? "" : aboutNode[0].InnerText
};
rssList.Add(rssItem);
}
return new SelectList(rssList, "Link", "Title", selectedValue);
}
This is the Index.ascx
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<GodsCreationTaxidermy.Helpers.BusinessDTO.RssList>" %>
<%
foreach (RssList rssItem in ViewData.Model)
{
Response.Write(string.Format("<div id=\"{0}\"><a href=\"{1}\" target=\"_blank\" /> <strong>{2}</strong></div>",
rssItem.Feed[0].ToString().Truncate(10), rssItem.Feed[1], rssItem.Feed[2].ToString().Truncate(100)));
} %>
And a normal call
<% Html.RenderPartial("Index");%>
}
FeedItemCass
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace GodsCreationTaxidermy.Models
{
public class RssFeedItem
{
public string Link { get; set; }
public string Title { get; set; }
public string About { get; set; }
}
}

Related

Xamarin Passing and checking data to other view using MVVM

So far I can pass the value to the other view but the problem is I don't know how to do this using MVVM. I tried the documentations and tutorial still no luck. How can I achieve this?
The flow of my project:
- The user will login, when the user provides the correct it will return a JSON array that contains the ContactID of the user.
- This ContactID now be pass to the other view. It will be used to synchronize the server to the local database and vice versa
My Questions are:
1. How can I pass the data to other view with MVVM?
2. How can I check if the data is passed correctly?
The Output of the HTTPWebRequest:
[{"ContactID":"1"}]
My Code:
LoginPageViewModel.cs
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Text;
using System.Windows.Input;
using TBSMobileApplication.Data;
using TBSMobileApplication.View;
using Xamarin.Essentials;
using Xamarin.Forms;
namespace TBSMobileApplication.ViewModel
{
public class LoginPageViewModel : INotifyPropertyChanged
{
void OnPropertyChanged(string PropertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}
public string username;
public string password;
public string Username
{
get { return username; }
set
{
username = value;
OnPropertyChanged(nameof(Username));
}
}
public string Password
{
get { return password; }
set
{
password = value;
OnPropertyChanged(nameof(Password));
}
}
public class LoggedInUser
{
public int ContactID { get; set; }
}
public ICommand LoginCommand { get; set; }
public LoginPageViewModel()
{
LoginCommand = new Command(OnLogin);
}
public void OnLogin()
{
if (string.IsNullOrEmpty(Username) || string.IsNullOrEmpty(Password))
{
MessagingCenter.Send(this, "Login Alert", Username);
}
else
{
var current = Connectivity.NetworkAccess;
if (current == NetworkAccess.Internet)
{
var link = "http://192.168.1.25:7777/TBS/test.php?User=" + Username + "&Password=" + Password;
var request = HttpWebRequest.Create(string.Format(#link));
request.ContentType = "application/json";
request.Method = "GET";
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
if (response.StatusCode != HttpStatusCode.OK)
{
Console.Out.WriteLine("Error fetching data. Server returned status code: {0}", response.StatusCode);
}
else
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
var content = reader.ReadToEnd();
if (content.Equals("[]") || string.IsNullOrWhiteSpace(content) || string.IsNullOrEmpty(content))
{
MessagingCenter.Send(this, "Http", Username);
}
else
{
var result = JsonConvert.DeserializeObject<List<LoggedInUser>>(content);
var contactId = result[0].ContactID;
Application.Current.MainPage.Navigation.PushAsync(new DatabaseSyncPage(contactId), true);
}
}
}
}
}
else
{
MessagingCenter.Send(this, "Not Connected", Username);
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
DatabaseSyncPage.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace TBSMobileApplication.View
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class DatabaseSyncPage : ContentPage
{
public DatabaseSyncPage (int contanctId)
{
InitializeComponent ();
}
}
}
If you are new to MVVM i would highly recommend using an MVVM helper framework such as Prism, MVVMCross or MVVMLight (there are even more).
I myself use Prism, I believe all of the frameworks are functionally very similar and it comes down more to preference here. I will show you how I pass data between views in my Prism based applications. Before we get started it would be worth to download the prism visual studio extensions and use the template pack to generate a prism project. I use the DryIoc container.
Imagine the scenario where we have ViewA (with ViewAViewModel) and ViewB (with ViewBViewModel). In View A we have an Entry and a Button, when the button is pressed the text from the entry in ViewA is passed to ViewB where it is displayed in a label.
You would first setup your prism project, creating a XAML fronted view for View A & B and then creating 2 class files and creating the relevant View Models (I'll show you how).
Firstly creating the following files:
ViewA (Xaml content page)
ViewB (Xaml content page)
ViewAViewModel (empty class)
ViewBViewModel (empty class)
In your app.cs register the views and view models:
//You must register these views with prism otherwise your app will crash!
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<NavigationPage>();
containerRegistry.RegisterForNavigation<ViewA, ViewAViewModel>();
containerRegistry.RegisterForNavigation<ViewB, ViewBViewModel>();
}
Now format your view models by adding the following:
public class ViewAViewModel : ViewModelBase
{
INavigationService _navigationService;
public ViewAViewModel(INavigationService navigationService) : base(navigationService)
{
Title = "ViewA";
_navigationService = navigationService;
}
}
Repeat the above step for ViewBViewModel also (changing the relevant names).
Now in the views xaml lets add some stuff! Add the following to ViewA.xaml (inside <ContentPage.Content></ContentPage.Content>:
<StackLayout>
<Entry Placeholder="Type Here..." Text="{Binding ViewAText}"/>
<Button Text="Navigate" Command="{Binding OnNavigateCommand}"/>
</StackLayout>
and in ViewB.xaml:
`<Label Text="{Binding TextFromViewA}"/>`
Now I've already added the binding for you, so lets make the properties!
In View Model A add:
private string _viewAText;
public string ViewAText
{
get { return _viewAText; }
set { SetProperty(ref _viewAText, value); }
}
public DelegateCommand OnNavigateCommand { get; set; }
private void OnNavigate()
{
//Do Something
}
Now we have a bindable property and a command for our button press, add the following to the constructor:
public ViewAViewModel(INavigationService navigationService) : base(navigationService)
{
Title = "ViewA";
_navigationService = navigationService;
_viewAText = string.Empty;
OnNavigateCommand = new DelegateCommand(OnNavigate);
}
Now View A can bind text from the entry control and has an event handler for the command!
Lets hop into View B and wire that up!
Add the property:
private string _textFromViewA;
public string TextFromViewA
{
get { return _textFromViewA; }
set { SetProperty(ref _textFromViewA, value); }
}
and in the constructor:
public ViewBViewModel(INavigationService navigationService) : base(navigationService)
{
Title = "ViewB";
TextFromViewA = string.Empty;
}
Now the label we added in ViewB is hooked up to the view model. Lets now pass the text from the entry in A to B!
Back in View A add the following to the OnNavigate method:
private void OnNavigate()
{
NavigationParameters navParams = new NavigationParameters();
navParams.Add("PassedValue", _viewAText);
_navigationService.NavigateAsync("ViewB", navParams);
}
The navigation service is incredibly powerful and allows you to pass a dictionary between views (NavigationParameters). In this code we have created some NavigationParameter, added the value of the text in our entry to them and then asked the navigationService (which handles all navigation from viewmodels in Prism) to navigate to ViewB, passing the parameters to it.
In View B we can listen for these parameters using some built in methods provided by Prism. If you type override in ViewBViewModel you will see the methods:
OnNavigatingTo
OnNavigatedTo
OnNavigatedFrom
In this case we want to use OnNavigatingTo (which is fired during the transition between the views). Pull that method in and the following:
public override void OnNavigatingTo(NavigationParameters parameters)
{
base.OnNavigatingTo(parameters);
if (parameters.ContainsKey("PassedValue"))
{
_textFromViewA = (string)parameters["PassedValue"];
RaisePropertyChanged("TextFromViewA");
}
}
Here we check if the parameters contain the value we added (by searching for the dictionary key) and then retrieve the value (casting it to a string since the dictionary is ). We then set the property the label is bound to = to the passed value and then use a prism method, RaisePropertyChanged() to raise a property changed event so that the label's binded value updates!
Below is a gif of the results!
This might be alot to take in. I would advise you start using an MVVM framework asap, they are really easy to use and I would consider them essential to making testable, decoupled MVVM xamarin apps!
For more on how prism works, I'd suggest to go read the docs and watch Brian Lagunas' appearance on the Xamarin Show!
Good Luck!
i had implemented the same and hope this helps you.
i have create a loginViewModel
public class LoginVerificationVM : BaseViewModel // INotifyPropertyChanged
{
private INavigation _navigation;
private string usermobileno;
public string UserMobileNo
{ get { return usermobileno; }set { usermobileno = value;
OnPropertyChanged("UserMobileNo"); }
}
public LoginVerificationVM(INavigation navigation, string mobileno)
{
UserMobileNo = mobileno;
_navigation = navigation;
}
public Command Login
{
get
{
return new Command(async () =>
{
bool status = await WebApi.CheckNetWorkStatus();
if (status == false)
{
MessageClass.messagesWindow("Check Ur Connectivity");
this.Isvisible = false;
return;
}
Isvisible = true;
UserAuth ud = new UserAuth();
ud.username = UserMobileNo; // UserMobileNo;
ud.password = Password; // Password
ud.grant_type = "password"; //GrantType
Isvisible = true;
// IsBusy = false;
await Task.Delay(100);
var json = Task.Run(() => WebApi.GetUserAuth(ud)).Result;
// IsBusy = false;
if (json.ErrorMessage == "true")
{
Application.Current.MainPage = new MasterPages.MasterPage(json.access_token); //or use _navigation.PushAsync(new ForgotPasswordOTP(UserMobileNo));
}
else
{
MessageClass.messagesWindow(json.ErrorMessage);
}
Isvisible = false;
});
}
}
}
Xaml Code
<Entry x:Name="PasswordEntry" Grid.Row="2" IsPassword="True" Placeholder="******" HorizontalTextAlignment="Center" FontAttributes="Bold" TextColor="Black" WidthRequest="150" HeightRequest="35" FontSize="13" Text="{Binding Password, Mode=TwoWay}" >
<Button x:Name="Login" Grid.Row="3" HorizontalOptions="Center" BorderRadius="8" Text="Login" WidthRequest="100" BackgroundColor="#f7941d" TextColor="White" Command="{Binding Login}" IsEnabled="{Binding Active,Mode=TwoWay}">
here is implementation to get data on navigated page view model
public ForgotPasswordOTP(string Ph)
{
InitializeComponent();
BindingContext = new ForgotPasswordOTPViewModel(this.Navigation,Ph);
}
and the last thing you need to do is bind your view with your viewmodel
** BindingContext = new LoginVerificationVM(this.Navigation);**
And the answer for the last question is you need to deserialize json in c#
which can be done in following way
var userData = JsonConvert.DeserializeObject<YourObject>(result);

single page with multiple partials and forms

What is the best practice for this:
I have a list of partials on one page. Each page has a form on it to save the data of the partial.
I do this like this on the main page:
#foreach (var taak in Model)
{
#Html.Action("DetailTaak", "Checklist", new { trouwTaakId = taak.Id })
}
Then the controller is this (where the data is filled):
public ActionResult DetailTaak(int trouwTaakId)
{
DTO.Trouw.TrouwTaak viewModel;
viewModel = _themaService.GetTrouwTaakByTrouwTaakId(trouwTaakId);
return View(viewModel);
}
The page gets build and the list is completed. Now when I want to save a partial using this code:
#using (Html.BeginForm("DetailTaak", "Checklist", FormMethod.Post, new { #class = "form-horizontal col-md-12", role = "form", id = #Model.Id }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.Id)
...
}
It works but what do I do so the mainpage doesn't have to be reloaded ? This is the post code:
[HttpPost]
public ActionResult DetailTaak(DTO.Trouw.TrouwTaak model)
{
if (ModelState.IsValid)
{
ViewBag.SaveSuccess = "Je instellingen zijn opgeslagen";
}
return View("DetailTaak", model);
}
With this post code I go to the DetailTaak page instead of staying on the main page and just updating the partial.
I am doing something wrong but I don't know which way to go.
kind regards

How to display the Image property in the Views of ASP.net MVC

I want to convert my code number of my card to QR image, so I added one reference to my project. Then I created one method in my Helper Class :
public static Image GenerateQRCode(String code)
{
QrEncoder qrEncoder = new QrEncoder(ErrorCorrectionLevel.H);
QrCode qrCode = new QrCode();
qrEncoder.TryEncode(code, out qrCode);
Renderer renderer = new Renderer(5, Brushes.Black, Brushes.White);
MemoryStream ms = new MemoryStream();
renderer.WriteToStream(qrCode.Matrix, ms, System.Drawing.Imaging.ImageFormat.Png);
return System.Drawing.Image.FromStream(ms);
}
And then I call this function in my view :
<%
System.Drawing.Image image = ICEWeb.HelperClasses.HelperClass.GenerateQRCode("test");
%>
But it display only System.Drawing.Bitmap, Does anyone knwo how to display the System.Drawing.Image that return from my function GenerateQRCode() ?
Thna
Do it MVCishly: by writing a custom action result. The GenerateQRCode method that you currently have is something that you could leave behind in the legacy application where it was taken from.
public class QRCodeResult : ActionResult
{
public QRCodeResult(string code)
{
Code = code;
}
public string Code { get; private set; }
public override void ExecuteResult(ControllerContext context)
{
var response = context.HttpContext.Response;
response.ContentType = "image/png";
QrEncoder qrEncoder = new QrEncoder(ErrorCorrectionLevel.H);
QrCode qrCode = new QrCode();
qrEncoder.TryEncode(Code, out qrCode);
Renderer renderer = new Renderer(5, Brushes.Black, Brushes.White);
renderer.WriteToStream(qrCode.Matrix, response.OutputStream, System.Drawing.Imaging.ImageFormat.Png);
}
}
and then a controller action:
public ActionResult QRCode(string code)
{
return new QRCodeResult(code);
}
and finally in some view where you want to display the QR code use an <img> tag pointing to the controller action you wrote:
<img src="<%: Url.Action("QRCode", new { code = "test" }) %>" alt="" />

Customise Validation summary

I have used html.ValidationSummary to get all errors displayed on top of the page.
This will render list with errors on top of the page.
Example:
<ul>
<li>UserName is invalid</li>
</ul>
I have how ever need to render every item instead of list as custom div with additional html tags inside.
I need every line to be rendered as short example below (this is only one line):
<div>
<div class="right"><a href="#closeError">Close error</div>
<div class="right"><a href="#Update">Update Field</div>
<label>Error:</label> Name on the page is invalid.
</div>
What is your opininon how to achieve this rendering?
I have considered to create html helper where i will take ModelState and get all errors, but not sure this will work...
I have considered to create html helper where i will take ModelState and get all errors, but not sure this will work...
Why wouldn't that work?
public static class ValidationExtensions
{
public static IHtmlString MyValidationSummary(this HtmlHelper htmlHelper)
{
var formContext = htmlHelper.ViewContext.ClientValidationEnabled
? htmlHelper.ViewContext.FormContext
: null;
if (formContext == null && htmlHelper.ViewData.ModelState.IsValid)
{
return null;
}
var sb = new StringBuilder();
var htmlSummary = new TagBuilder("div");
var modelStates = htmlHelper.ViewData.ModelState.Values;
sb.AppendLine("<div class=\"right\"><a href=\"#closeError\">Close error</div>");
sb.AppendLine("<div class=\"right\"><a href=\"#Update\">Update Field</div>");
if (modelStates != null)
{
foreach (ModelState modelState in modelStates)
{
foreach (ModelError modelError in modelState.Errors)
{
var userErrorMessageOrDefault = GetUserErrorMessageOrDefault(modelError);
if (!string.IsNullOrEmpty(userErrorMessageOrDefault))
{
sb.AppendFormat("<label>Error:</label> {0}{1}", htmlHelper.Encode(userErrorMessageOrDefault), Environment.NewLine);
}
}
}
}
htmlSummary.InnerHtml = sb.ToString();
if (formContext != null)
{
formContext.ReplaceValidationSummary = true;
}
return MvcHtmlString.Create(htmlSummary.ToString(TagRenderMode.Normal));
}
private static string GetUserErrorMessageOrDefault(ModelError error)
{
if (!string.IsNullOrEmpty(error.ErrorMessage))
{
return error.ErrorMessage;
}
return null;
}
}
and then:
<%= Html.MyValidationSummary() %>

SelectList Object selectedValue issue

I'm having troubles with the selectedValue option for SelectedItems, for some reason it won't select the item despite it being in the list...
My Controller:
public ActionResult CreateTransformer(string edit)
{
var equipment = GenIDQueries.FindEquipment(edit);
ViewData["Feeder"] = new SelectList(GenIDQueries.GetFeeders(equipment.OpsCentre.ToString()),
"CircuitID",
"CircuitDescription",
equipment.Feeder);
return View(equipment);
}
equipment.Feeder is of type Integer.
My View:
<p>
<b><%=Html.LabelFor(m=>m.Feeder) %>:</b><font color="red">*</font>
<%=Html.DropDownListFor(m=>m.Feeder, ViewData["Feeder"] as SelectList, "") %>
<%= Html.ValidationMessageFor(m => m.Feeder)%>
</p>
My GenIDQueries.GetFeeders:
public static IEnumerable<Circuit> GetFeeders(string distNo)
{
int distNoNumber;
if ( int.TryParse(distNo, out distNoNumber))
{
return ActiveRecordLinq.AsQueryable<Circuit>()
.Where(x => x.DistrictCircuitRelations
.Any(y => y.District.DistrictNo == distNoNumber))
.OrderBy(x => x.CircuitDescription)
.Select(x => new Circuit
{
CircuitID = x.CircuitID,
CircuitDescription = x.CircuitDescription
});
}
return new List<Circuit>();
}
I have verified that the element I wanted to select is indeed returned by GenIDQueries, however when the page loads it never selects that option, in the HTML source code, the item is not selected either.
Thanks for the help!
When setting the selected value you should set it to the selected CircuitID and not the Feeder object.
Why are you using this Plague of ViewData? I consider ViewData as a virus started at Microsoft open space laboratories and spread through internet blog posts and articles.
View models are the way to go in ASP.NET MVC:
Model:
public class MyViewModel
{
public string SelectedValue { get; set; }
public IEnumerable<SelectListItem> Items { get; set; }
}
Controller:
public ActionResult CreateTransformer(string edit)
{
var equipment = GenIDQueries.FindEquipment(edit);
var items = GenIDQueries.GetFeeders(equipment.OpsCentre.ToString());
var model = new MyViewModel
{
SelectedValue = equipement.CircuitID,
Items = new SelectList(items, "CircuitID", "CircuitDescription")
};
return View(model);
}
View:
<%= Html.DropDownListFor(m => m.CircuitID, Model.Items, "") %>
<%= Html.ValidationMessageFor(m => m.CircuitID) %>