Many changes :
* JsonReaderError.aspx: display a nice json conversion error * CalendarEntryList.cs: new Google data for the calendar entries * JsonReaderError.cs: Json error model * README.md: Documentation url * NpgsqlBlogProvider.cs: Update the blog post title * BlogsController.cs: - Updating the blog post title - bug fix rendering the avatar * FrontOfficeController.cs: - the client cannot modify its estimation * GoogleController.cs: - implementing the calendar entries retrieval * HomeController.cs: - the home start page from configuration parameter named "StartPage" * Global.asax.cs: - back to a clean global.asax * style.css: showing the main area with a background transparent color * Post.aspx: Bug fix: the message was displayed two times (we keep the one from app.master) * UserPost.aspx: the blog title comes from the poster profile found in ViewData * DateQuery.aspx: implementing the date query * Web.config: the start page now comes from Web.config * Web.csproj: the Sql db creation script should not be deployed, neither as package.config * BlogManager.cs: updating the blog post title * BlogProvider.cs: yavscModel/Blogs/BlogManager.cs * YavscModel.csproj: new cs files to compile * App.master: returning from the Google login
This commit is contained in:
@ -68,15 +68,19 @@ namespace Npgsql.Web.Blog
|
||||
}
|
||||
return cmts.ToArray();
|
||||
}
|
||||
public override void UpdatePost (long postid, string content, bool visible)
|
||||
public override void UpdatePost (long postid, string title, string content, bool visible)
|
||||
{
|
||||
using (NpgsqlConnection cnx = new NpgsqlConnection(connectionString))
|
||||
using (NpgsqlCommand cmd = cnx.CreateCommand()) {
|
||||
DateTime now = DateTime.Now;
|
||||
cmd.CommandText =
|
||||
"update blog set modified=@now, bcontent=@content, " +
|
||||
"visible = @visible where _id = @id";
|
||||
"update blog set modified=@now," +
|
||||
" title = @title," +
|
||||
" bcontent=@content, " +
|
||||
" visible = @visible " +
|
||||
"where _id = @id";
|
||||
cmd.Parameters.Add ("@now", now);
|
||||
cmd.Parameters.Add ("@title", title);
|
||||
cmd.Parameters.Add ("@content", content);
|
||||
cmd.Parameters.Add ("@visible", visible);
|
||||
cmd.Parameters.Add ("@id", postid);
|
||||
|
@ -4,3 +4,6 @@ yavsc
|
||||
Yet Another Very Small Company
|
||||
|
||||
For the moment, overall a little home made blogging system.
|
||||
|
||||
See <http://www.pschneider.fr> for more information
|
||||
|
||||
|
@ -122,6 +122,7 @@ namespace Yavsc.Controllers
|
||||
return View ("TitleNotFound");
|
||||
ViewData ["BlogUserProfile"] = pr;
|
||||
ViewData ["BlogTitle"] = pr.BlogTitle;
|
||||
ViewData ["HasAvatar"] = pr.avatar != null;
|
||||
MembershipUser u = Membership.GetUser ();
|
||||
if (u != null)
|
||||
ViewData ["UserName"] = u.UserName;
|
||||
@ -159,8 +160,6 @@ namespace Yavsc.Controllers
|
||||
string un = Membership.GetUser ().UserName;
|
||||
if (String.IsNullOrEmpty (user))
|
||||
user = un;
|
||||
if (un != user)
|
||||
ViewData ["Message"] = string.Format ("Vous n'êtes pas {0}!", user);
|
||||
ViewData ["UserName"] = un;
|
||||
return View (new BlogEditEntryModel { Title = title });
|
||||
}
|
||||
@ -187,7 +186,7 @@ namespace Yavsc.Controllers
|
||||
ViewData ["BlogUser"] = Membership.GetUser ().UserName;
|
||||
if (ModelState.IsValid) {
|
||||
if (!model.Preview) {
|
||||
BlogManager.UpdatePost (model.Id, model.Content, model.Visible);
|
||||
BlogManager.UpdatePost (model.Id, model.Title, model.Content, model.Visible);
|
||||
return UserPost (model);
|
||||
}
|
||||
}
|
||||
@ -247,11 +246,9 @@ namespace Yavsc.Controllers
|
||||
return File (fia.OpenRead (), defaultAvatarMimetype);
|
||||
}
|
||||
WebRequest wr = WebRequest.Create(avpath);
|
||||
using (WebResponse resp = wr.GetResponse ()) {
|
||||
using (Stream str = resp.GetResponseStream ()) {
|
||||
return File (str, resp.ContentType);
|
||||
}
|
||||
}
|
||||
WebResponse resp = wr.GetResponse ();
|
||||
Stream str = resp.GetResponseStream ();
|
||||
return File (str, resp.ContentType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -71,7 +71,6 @@ namespace Yavsc.Controllers
|
||||
}
|
||||
if (ModelState.IsValid) {
|
||||
if (username != model.Responsible
|
||||
&& username != model.Client
|
||||
&& !Roles.IsUserInRole ("FrontOffice"))
|
||||
throw new UnauthorizedAccessException ("You're not allowed to modify this estimate");
|
||||
|
||||
|
@ -26,22 +26,22 @@ namespace Yavsc.Controllers
|
||||
// 2015-01-01T10:00:00-07:00
|
||||
// private string API_KEY="AIzaSyBV_LQHb22nGgjNvFzZwnQHjao3Q7IewRw";
|
||||
|
||||
private string getPeopleUri = "https://www.googleapis.com/plus/v1/people";
|
||||
private string getCalListUri = "https://www.googleapis.com/calendar/v3/users/me/calendarList";
|
||||
private string getCalEntriesUri = "https://developers.google.com/google-apps/calendar/v3/reference/events/list";
|
||||
private static string getPeopleUri = "https://www.googleapis.com/plus/v1/people";
|
||||
private static string getCalListUri = "https://www.googleapis.com/calendar/v3/users/me/calendarList";
|
||||
private static string getCalEntriesUri = "https://www.googleapis.com/calendar/v3/calendars/{0}/events";
|
||||
|
||||
private string CLIENT_ID = "325408689282-6bekh7p3guj4k0f3301a6frf025cnrk1.apps.googleusercontent.com";
|
||||
private string CLIENT_SECRET = "MaxYcvJJCs2gDGvaELZbzwfL";
|
||||
private static string CLIENT_ID = "325408689282-6bekh7p3guj4k0f3301a6frf025cnrk1.apps.googleusercontent.com";
|
||||
private static string CLIENT_SECRET = "MaxYcvJJCs2gDGvaELZbzwfL";
|
||||
|
||||
string[] SCOPES = {
|
||||
private static string[] SCOPES = {
|
||||
"openid",
|
||||
"profile",
|
||||
"email"
|
||||
};
|
||||
|
||||
string tokenUri = "https://accounts.google.com/o/oauth2/token";
|
||||
string authUri = "https://accounts.google.com/o/oauth2/auth";
|
||||
|
||||
private static string tokenUri = "https://accounts.google.com/o/oauth2/token";
|
||||
private static string authUri = "https://accounts.google.com/o/oauth2/auth";
|
||||
private static string dateFormat = "yyyy-MM-dd'T'HH:mm:ss.fffK";
|
||||
private string SetSessionSate ()
|
||||
{
|
||||
Random rand = new Random ();
|
||||
@ -363,14 +363,24 @@ namespace Yavsc.Controllers
|
||||
ModelState.AddModelError ("MinTime", "This first date must be lower than the second one.");
|
||||
return View (model);
|
||||
}
|
||||
ProfileBase upr = ProfileBase.Create (model.UserName);
|
||||
if (upr == null) {
|
||||
var muc = Membership.FindUsersByName (model.UserName);
|
||||
if (muc.Count==0) {
|
||||
ModelState.AddModelError ("UserName", "Non existent user");
|
||||
return View (model);
|
||||
}
|
||||
ProfileBase upr = ProfileBase.Create (model.UserName);
|
||||
|
||||
|
||||
HttpWebRequest webreq = WebRequest.CreateHttp (getCalEntriesUri);
|
||||
string calid = (string) upr.GetPropertyValue ("gcalid");
|
||||
if (string.IsNullOrWhiteSpace(calid)) {
|
||||
ModelState.AddModelError ("UserName", "L'utilisateur n'a pas de calendrier Google associé.");
|
||||
return View (model);
|
||||
}
|
||||
HttpWebRequest webreq = WebRequest.CreateHttp (
|
||||
string.Format(
|
||||
getCalEntriesUri, calid)+
|
||||
string.Format("?singleEvents=true&orderBy=startTime&timeMin={0}&timeMax={1}",
|
||||
model.MinDate.ToString(dateFormat),model.MaxDate.ToString(dateFormat))
|
||||
);
|
||||
webreq.Headers.Add (HttpRequestHeader.Authorization, GetFreshGoogleCredential(upr));
|
||||
webreq.Method = "GET";
|
||||
webreq.ContentType = "application/http";
|
||||
@ -378,12 +388,18 @@ namespace Yavsc.Controllers
|
||||
using (Stream respstream = resp.GetResponseStream ()) {
|
||||
using (StreamReader readresp = new StreamReader (respstream, Encoding.UTF8)) {
|
||||
string responseStr = readresp.ReadToEnd ();
|
||||
CalendarList res = JsonConvert.DeserializeObject<CalendarList> (responseStr);
|
||||
try {
|
||||
CalendarEntryList res = JsonConvert.DeserializeObject<CalendarEntryList> (responseStr);
|
||||
ViewData ["json"] = responseStr;
|
||||
return View (res);
|
||||
}
|
||||
catch (JsonReaderException ex) {
|
||||
return View ("JsonReaderError", new JsonReaderError() {Text= responseStr, Excepx = ex});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return View (model);
|
||||
}
|
||||
|
@ -69,7 +69,9 @@ namespace Yavsc.Controllers
|
||||
|
||||
public ActionResult Index ()
|
||||
{
|
||||
string cn = CultureInfo.CurrentCulture.Name;
|
||||
string startPage = WebConfigurationManager.AppSettings ["StartPage"];
|
||||
if (startPage != null)
|
||||
Redirect (startPage);
|
||||
ViewData ["Message"] = LocalizedText.Welcome;
|
||||
return View ();
|
||||
}
|
||||
|
@ -25,17 +25,7 @@ namespace Yavsc
|
||||
"Blog",
|
||||
"Blog/{user}/{title}",
|
||||
new { controller = "Blogs", action = "Index", user=UrlParameter.Optional, title = UrlParameter.Optional }
|
||||
); /*
|
||||
routes.MapRoute (
|
||||
"Blogs",
|
||||
"Blogs/{action}/{user}/{title}",
|
||||
new { controller = "Blogs", action = "Index", user=UrlParameter.Optional, title = UrlParameter.Optional}
|
||||
);*/ /*
|
||||
routes.MapRoute (
|
||||
"Home",
|
||||
"Home/Index",
|
||||
new { controller = "Blogs", action = "Index", user="paul", title = "Documentation" }
|
||||
);*/
|
||||
);
|
||||
|
||||
/*routes.MapRoute (
|
||||
"Default",
|
||||
@ -45,7 +35,7 @@ namespace Yavsc
|
||||
routes.MapRoute (
|
||||
"Default",
|
||||
"{controller}/{action}/{user}/{title}",
|
||||
new { controller = "Blogs", action = "Index", user="paul", title = "Documentation"}
|
||||
new { controller = "Blogs", action = "Index", user=UrlParameter.Optional, title = UrlParameter.Optional }
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@
|
||||
<span class="hidcom"> Page d'accueil </span>
|
||||
<%= Html.ActionLink("Login", "Login", "Account", new { returnUrl=Request.Url.PathAndQuery }, new { @class="actionlink" } ) %>
|
||||
<span class="hidcom">Pour pouvoir poster ou commenter</span>
|
||||
<a href="<%=Request.Url.Scheme + "://" + Request.Url.Authority + "/Google/Login"%>?returnUrl=<%=ViewData["returnUrl"]%>" class="actionlink">
|
||||
<a href="<%=Request.Url.Scheme + "://" + Request.Url.Authority + "/Google/Login"%>?returnUrl=<%=Request.Url.PathAndQuery%>" class="actionlink">
|
||||
<img src="/images/sign-in-with-google-s.png" style="max-height:1.5em; max-width:6em;" alt="Google sign in">
|
||||
</a>
|
||||
<span class="hidcom">S'authentifier avec son compte Google+</span>
|
||||
|
@ -9,7 +9,7 @@ body {
|
||||
}
|
||||
|
||||
main {
|
||||
background-color: rgba(0,0,0,0.8);
|
||||
background-color: rgba(17,0,23,0.65);
|
||||
float:left;
|
||||
margin:.5em;
|
||||
}
|
||||
@ -24,9 +24,13 @@ video,img {
|
||||
max-width:100%;
|
||||
max-height:75%;
|
||||
position:relative;
|
||||
top:4px;
|
||||
}
|
||||
.panel { max-width: 17em;
|
||||
|
||||
.panel {
|
||||
background-color: rgba(16,32,32,0.8);
|
||||
padding: 1em; margin: 0.5em;
|
||||
border-radius:25px; border: solid 1px #000060;
|
||||
max-width: 17em;
|
||||
max-height:30em; border:solid green 1px;}
|
||||
|
||||
footer {
|
||||
@ -39,8 +43,8 @@ footer {
|
||||
justify-content: space-around;
|
||||
z-index:-1;
|
||||
}
|
||||
|
||||
footer img { max-height: 2em; }
|
||||
.actionlink img { top:4px; }
|
||||
footer img { max-height: 2em; }
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
|
@ -14,9 +14,7 @@ Nouveau billet -
|
||||
</asp:Content>
|
||||
|
||||
<asp:Content ContentPlaceHolderID="MainContent" ID="MainContentContent" runat="server">
|
||||
<div class="message">
|
||||
<%= Html.Encode(ViewData["Message"]) %>
|
||||
</div>
|
||||
|
||||
<% if (Model != null ) if (Model.Content != null ) { %>
|
||||
<div class="blogpost">
|
||||
<%= BBCodeHelper.Parser.ToHtml(Model.Content) %>
|
||||
@ -54,7 +52,7 @@ Nouveau billet -
|
||||
<%= Html.ValidationMessage("Preview", "*") %>
|
||||
<br/>
|
||||
<%= Html.Hidden("Id") %>
|
||||
<input type="button" id="btnpreview" value="<%=LocalizedText.Preview %>"/>
|
||||
<input type="button" id="btnpreview" value="<%= T.GetString("Preview") %>"/>
|
||||
<input type="submit"/>
|
||||
<input type="button" id="testbtn">
|
||||
<script language="Javascript">
|
||||
|
@ -1,11 +1,18 @@
|
||||
<%@ Page Title="Billet" Language="C#" Inherits="System.Web.Mvc.ViewPage<BlogEntry>" MasterPageFile="~/Models/App.master"%>
|
||||
<asp:Content ContentPlaceHolderID="init" ID="init1" runat="server">
|
||||
<% Title = Model.Title+" - "+ViewData["BlogTitle"]; %>
|
||||
<% Title = Model.Title+" - "+((string) ((Profile)ViewData["BlogUserProfile"]).BlogTitle) ; %>
|
||||
</asp:Content>
|
||||
<asp:Content ContentPlaceHolderID="overHeaderOne" ID="header1" runat="server">
|
||||
<h1 class="blogtitle"><%= Html.ActionLink(Model.Title,"UserPost",new{user=Model.UserName,title=Model.Title}) %> -
|
||||
<a href="/Blog/<%=Model.UserName%>">
|
||||
<% if ((bool)ViewData["HasAvatar"]) { %>
|
||||
<img class="avatar" src="/Blogs/Avatar?user=<%=Model.UserName%>" alt="<%=Model.UserName%>"/> <%=ViewData["BlogTitle"]%></a>
|
||||
<% } else { %>
|
||||
<a href="/Blog/<%=Model.UserName%>">
|
||||
<%=Html.Encode(ViewData["BlogTitle"])%>
|
||||
</a>
|
||||
<% } %>
|
||||
|
||||
</h1>
|
||||
</asp:Content>
|
||||
|
||||
|
@ -69,8 +69,15 @@ return Globalize.format( new Date(value), "t" );
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Durée minimale : <input type="text" id="Duration" />
|
||||
Durée minimale : <input type="text" id="Duration" class="time"/>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<%= Html.LabelFor(model=>model.UserName) %>:<br>
|
||||
<%= Html.TextBoxFor(model=>model.UserName) %><br>
|
||||
<%= Html.ValidationMessageFor(model=>model.UserName) %>
|
||||
</p>
|
||||
|
||||
<script>
|
||||
$(function() {
|
||||
|
||||
|
12
web/Views/Google/JsonReaderError.aspx
Normal file
12
web/Views/Google/JsonReaderError.aspx
Normal file
@ -0,0 +1,12 @@
|
||||
<%@ Page Title="Json reader error" Language="C#" Inherits="System.Web.Mvc.ViewPage<JsonReaderError>" MasterPageFile="~/Models/App.master" %>
|
||||
<asp:Content ContentPlaceHolderID="MainContent" ID="MainContentContent" runat="server">
|
||||
|
||||
<h2><%= Html.Encode(Model.Excepx.Message)%></h2>
|
||||
|
||||
<pre>
|
||||
<code>
|
||||
<%= Html.Encode(Model.Text) %>
|
||||
</code></pre>
|
||||
|
||||
</asp:Content>
|
||||
|
@ -300,7 +300,10 @@ http://msdn2.microsoft.com/en-us/library/b5ysx397.aspx
|
||||
<add key="SmtpServer" value="smtp.free.fr" />
|
||||
<add key="AdminEMail" value="paulschneider@free.fr" />
|
||||
<add key="OwnerEMail" value="paul@127.0.0.1" />
|
||||
<add key="Name" value="Psc" />
|
||||
<add key="Name" value="Psc" />
|
||||
<!-- do not point "/Home/index" with the value for the "StartPage",
|
||||
it would result in a redirection infinite loop -->
|
||||
<add key="StartPage" value="/Blog" />
|
||||
<add key="DefaultAvatar" value="/images/noavatar.png;image/png" />
|
||||
<add key="RegistrationMessage" value="/RegistrationMail.txt" />
|
||||
<add key="ClientValidationEnabled" value="true" />
|
||||
|
@ -239,9 +239,7 @@
|
||||
<Content Include="Views\Home\ReferencedAssemblies.aspx" />
|
||||
<Content Include="Catalog.xml" />
|
||||
<Content Include="RegistrationMail.txt" />
|
||||
<Content Include="instdbws.sql" />
|
||||
<Content Include="Views\FrontOffice\Writting.ascx" />
|
||||
<Content Include="packages.config" />
|
||||
<Content Include="Views\Google\Login.aspx" />
|
||||
<Content Include="Scripts\jquery-2.1.1-vsdoc.js" />
|
||||
<Content Include="Scripts\jquery-2.1.1.js" />
|
||||
@ -266,6 +264,7 @@
|
||||
<Content Include="Views\FrontOffice\Index.aspx" />
|
||||
<Content Include="Views\BackOffice\Index.aspx" />
|
||||
<Content Include="images\sign-in-with-google-s.png" />
|
||||
<Content Include="Views\Google\JsonReaderError.aspx" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
|
||||
@ -289,6 +288,8 @@
|
||||
</None>
|
||||
<None Include="install\instdb.sql" />
|
||||
<None Include="Scripts\jquery-2.1.1.min.map" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="instdbws.sql" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\NpgsqlMRPProviders\NpgsqlMRPProviders.csproj">
|
||||
|
@ -39,9 +39,9 @@ namespace Yavsc.Model.Blogs
|
||||
{
|
||||
Provider.Post(username, title, content, visible );
|
||||
}
|
||||
public static void UpdatePost(long postid, string content, bool visible)
|
||||
public static void UpdatePost(long postid, string title, string content, bool visible)
|
||||
{
|
||||
Provider.UpdatePost(postid, content, visible);
|
||||
Provider.UpdatePost(postid, title, content, visible);
|
||||
}
|
||||
public static BlogEntryCollection FindPost (string pattern, FindBlogEntryFlags searchflags, int pageIndex, int pageSize, out int totalRecords)
|
||||
{
|
||||
|
@ -12,7 +12,7 @@ namespace Yavsc.Model.Blogs
|
||||
public abstract long GetPostId (string username, string title);
|
||||
|
||||
public abstract long Post (string username, string title, string content, bool visible);
|
||||
public abstract void UpdatePost (long postid, string content, bool visible);
|
||||
public abstract void UpdatePost (long postid, string title, string content, bool visible);
|
||||
public abstract BlogEntryCollection FindPost (string pattern, FindBlogEntryFlags searchflags,
|
||||
int pageIndex, int pageSize, out int totalRecords);
|
||||
public abstract void RemovePost (string username, string title);
|
||||
|
30
yavscModel/Google/CalendarEntryList.cs
Normal file
30
yavscModel/Google/CalendarEntryList.cs
Normal file
@ -0,0 +1,30 @@
|
||||
//
|
||||
// CalendarEntry.cs
|
||||
//
|
||||
// Author:
|
||||
// Paul Schneider <paulschneider@free.fr>
|
||||
//
|
||||
// Copyright (c) 2015 Paul Schneider
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
|
||||
namespace Yavsc.Model.Google
|
||||
{
|
||||
public class CalendarEntryList
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
31
yavscModel/Google/JsonReaderError.cs
Normal file
31
yavscModel/Google/JsonReaderError.cs
Normal file
@ -0,0 +1,31 @@
|
||||
//
|
||||
// JsonReaderError.cs
|
||||
//
|
||||
// Author:
|
||||
// Paul Schneider <paulschneider@free.fr>
|
||||
//
|
||||
// Copyright (c) 2015 Paul Schneider
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
|
||||
namespace Yavsc.Model.Google
|
||||
{
|
||||
public class JsonReaderError
|
||||
{
|
||||
public string Text { get; set; }
|
||||
public Exception Excepx { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -91,6 +91,8 @@
|
||||
<Compile Include="Google\CalendarList.cs" />
|
||||
<Compile Include="Google\CalendarListEntry.cs" />
|
||||
<Compile Include="Google\AskForADate.cs" />
|
||||
<Compile Include="Google\JsonReaderError.cs" />
|
||||
<Compile Include="Google\CalendarEntryList.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ItemGroup>
|
||||
|
Reference in New Issue
Block a user